Reference data types behave differently from primitive data types. As you saw in the previous section, to use a primitive data type variable in a program you simply declare the variable and assign it a value directly. You can’t do this with reference data types. (You can as of Java version 1.5. This is referred to as autoboxing. But I will delay coverage of autoboxing until later in the book.) There’s another step involved that requires the use of the new operator to allocate memory, create an object, and assign the value of the object’s memory location to the reference identifier. Only after the object is created in memory can you then use the reference to access the object’s functionality. The following sections discuss this process in detail.
A reference variable is an identifier that can be assigned the value of an object’s memory location during program runtime. Once the value of an object’s memory location has been assigned to the reference it can be used to access the object’s functionality. Once you know how to use reference variables the whole Java platform API is at your service.
An object is a region of memory that contains the data associated with a particular instance of a class. The object, or instance, is created when the new operator is used to dynamically allocate system memory for the object’s use. The act of creating an object is referred to as instantiation.
Example 6.12 gives the source code for a class named TestClassTwo showing how to use the new operator to instantiate an object and assign its memory location value to a reference variable.
Example 6.12: TestClassTwo.java
1 public class TestClassTwo { 2 public static void main(String[] args){ 3 Object object_reference = new Object(); 4 System.out.println(object_reference.toString()); 5 } 6 }
In this example I am creating an object of type java.lang.Object. A reference variable named object_reference is declared on line 3. On the same line the new operator is used to create the object in memory and assign its location value to object_reference. Notice that the new operator is followed by the class name of the object you want to create. In this case the name of the class is Object. Appended to the Object class name is a set of parentheses. This is referred to as a constructor call. A constructor is a special method whose purpose is to properly set up or construct an instance of an object in memory. You’ll learn more about constructors in chapter 9.
After the object is created in memory its functionality can be accessed via the reference variable as is shown on line 4. In this case, the toString() method is being called via the object_reference variable. The toString() method returns a String representation of the object which includes its name followed by a hexadecimal value that represents the object’s hashcode. (An object’s hashcode is an integer value that is unique to that particular object.) This string is then used as an argument to the System.out.println() method. Figure 6-10 shows the results of running this program.
Figure 6-10: Results of Running Example 6.12
Figure 6-11 shows graphically what happens when an object is instantiated with the new operator. Memory space for dynamically created objects is reserved in an area of memory referred to as the heap. Once space has been reserved on the heap an integer value representing the object’s memory location is returned to the requesting program and assigned to the object_reference variable. (An object’s memory address may be used to compute its hashcode value but this is not strictly required.) In the case of example 6.12 above, when that program was run on my computer the newly created object had a hashcode value of 8813f2 as is shown in figure 6-10 above.
Figure 6-11: Creating an Object with the new Operator
When you want to create a new object and assign its memory location to an existing reference variable just go ahead and use the new operator again. The Java virtual machine will manage the memory issues for you. Using what is referred to as a garbage collector, the Java virtual machine will periodically check the objects in the heap to ensure they have valid references pointing to them. If not, they are tagged for collection and the memory space they occupy is freed up for use by other objects. Example 6.13 shows the object_reference variable being reused to hold the location of a new object.
Example 6.13: TestClassTwo.java (mod 2)
1 public class TestClassTwo { 2 public static void main(String[] args){ 3 Object object_reference = new Object(); 4 System.out.println(object_reference.toString()); 5 object_reference = new Object(); 6 System.out.println(object_reference.toString()); 7 } 8 }
Notice that on line 5 the new operator is being used to create another Object class object on the heap. The new object’s memory location value will overwrite the old value stored in the object_reference variable and it will now point to, or reference, the newly created object. Figure 6-12 shows the results of running this program.
Figure 6-12: Creating Another Object with the new Operator
Notice now that the second object has a completely new memory location as is shown in the program output. Figure 6-13 graphically illustrates what’s happening here.
Figure 6-13: Reusing the object_reference Variable
Now that the object_reference variable points to a new object, the old object it used to point to no longer has a reference pointing to it. It can now be garbage collected and its memory reclaimed for use by new objects as required.