Sunday, July 12, 2009

Class and Object

Class vs Object

To clarify the concepts of class vs object to newcomers of object-oriented programming, analogies to the physical world are often used. For example, a class is commonly described as a template or a blueprint from which to create an object.

I find, however, that the best way to describe a class is to compare it a cookie cutter, and the cookies are the objects. The process of creating objects from a class is called instantiation.

When you write a Java program, part of the work is to define a collection of classes and their characteristics, much like making a cookie cutter of, say, a gingerbread man. The actual instantiation will occur at runtime in which multiple objects may be created from a single class, just as you would use the cookie cutter to cut out multiple gingerbread men cookies out of the cookie dough using the gingerbread man cookie cutter. Each object is unique, although they are described by the same attributes, just as each gingerbread man is unique even though they all have head, arms and legs.

What Happens Behind the Scene When You Instantiate An Object

A way to enhance the understanding of the relationship between class and object is to know aht the computer actually does during the process of instantiation.

At runtime, a class you wrote has to go through two phases before it can be used: (1) class loading and (2) instantiation.

Normally, loading a class from compiled class files (*.class files) is automatic and you do not have to worry about it. When the class is loaded, memory for static members (variables and methods) are allocated and ready to use. Note that these variables are shared between objects of this class, so static variables are like global variables.

When an object is instantiated from a class, memory for non-static members (aka instance variables) are allocated. You can have separate sets of these memories, so objects are unique and do not interfere with each other.

An Example

Let's use an example to illustrate. Note that the memory map illustration is simplified for clarity, but the critical concepts are accurate.

ABC is a class containing a static String variable and a String instance variable.
public class ABC
{
public static String xyz = "This is a static string.";
public String abc = "This is an instance string";
}
The following is our main class:
public class Main
{
public static void main(String[] args)
{
System.out.println(ABC.xyz); ...................... (1)

// Create one instance.
ABC abcInstance1 = new ABC(); ..................... (2)
System.out.println(abcInstance.abc);

// Change that value of abc.
abcInstance1.abc = "Change it"; ................... (3)

// Create another instance.
ABC abcInstance2 = new ABC(); ..................... (4)

// Changing the value of abc for abcInstance1 does not // affect the value of abc in abcInstance2.
System.out.println(abcInstance2.abc);

}
}

When run, the first line executed (1) loads class ABC and memory is allocated for ABC's static member - in this case, the static variable xyz. We may imagine the computer's memory map to look reasonably like this:

+----------------------------------------------------+
| xyz | This is a static string |
+----------------------------------------------------+
| | |
+----------------------------------------------------+
| | |
+----------------------------------------------------+
| | |
+----------------------------------------------------+
:

When ABC is instantiated at (2), the memory is allocated for the variable abc. The memory map now looks like this, and the println statement after (2) proves it:

+----------------------------------------------------+
| xyz | This is a static string |
+----------------------------------------------------+
| abc (for abcInstance1)| This is an instance string |
+----------------------------------------------------+
| | |
+----------------------------------------------------+
| | |
+----------------------------------------------------+
:


When abcInstance1's abc is modified to "Change it" at (3), the memory location for abcInstance1's abc gets a new value:

+----------------------------------------------------+
| xyz | This is a static string |
+----------------------------------------------------+
| abc (for abcInstance1)| Change it |
+----------------------------------------------------+
| | |
+----------------------------------------------------+
| | |
+----------------------------------------------------+
:


At (4), another instance of ABC, abcInstance2, is created, and new memory for abc is allocated for abcInstance2. Note that xyz is remains the same, shared between abcInstance1 and abcInstance2.

+----------------------------------------------------+
| xyz | This is a static string |
+----------------------------------------------------+
| abc (for abcInstance1)| Change it |
+----------------------------------------------------+
| abc (for abcInstance2)| This is an instance string |
+----------------------------------------------------+
| | |
+----------------------------------------------------+
:


References
  1. Patrick Niemeyer and Jonathan Knudsen, Learning Java, 3rd ed., O'Reilly (2005), Chapter 5.


No comments:

Post a Comment