7.4. Accessing Objects via Reference Variables

 
[Page 216 ( continued )]

7.4. Accessing Objects via Reference Variables

Newly created objects are allocated in the memory. How can they be accessed? The answer is given in this section.

7.4.1. Reference Variables and Reference Types

Objects are accessed via object reference variables , which contain references to the objects. Such variables are declared using the following syntax:

 ClassName objectRefVar; 

A class defines a type, known as a reference type . Any variable of the class type can reference to an instance of the class. The following statement declares the variable myCircle to be of the Circle type:

 Circle myCircle; 


[Page 217]

The variable myCircle can reference a Circle object. The next statement creates an object and assigns its reference to myCircle .

 myCircle =   new   Circle(); 

Using the syntax shown below, you can write one statement that combines the declaration of an object reference variable, the creation of an object, and the assigning of an object reference to the variable.

 ClassName objectRefVar =   new   ClassName(); 

Here is an example:

 Circle myCircle =   new   Circle(); 

The variable myCircle holds a reference to a Circle object.

Note

An object reference variable that appears to hold an object actually contains a reference to that object. Strictly speaking, an object reference variable and an object are different, but most of the time the distinction between them can be ignored. So it is fine, for simplicity, to say that myCircle is a Circle object rather than a more long-winded phrase stating that myCircle is a variable that contains a reference to a Circle object. When the distinction makes a subtle difference, the long phrase should be used.


Note

Arrays are treated as objects in Java. Arrays are created using the new operator. An array variable is actually a variable that contains a reference to an array.


7.4.2. Accessing an Object's Data and Methods

After an object is created, its data can be accessed and its methods invoked using the dot operator ( . ), also known as the object member access operator :

  • objectRefVar.dataField references a data field in the object.

  • objectRefVar.method(arguments) invokes a method on the object.

For example, myCircle.radius references the radius in myCircle , and myCircle.getArea() invokes the getArea method on myCircle . Methods are invoked as operations on objects.

The data field radius is referred to as an instance variable because it is dependent on a specific instance. For the same reason, the method getArea is referred to as an instance method , because you can only invoke it on a specific instance. The object on which an instance method is invoked is referred to as a calling object .

Note

Most of the time, you create an object and assign it to a variable. Later you can use the variable to reference the object. Occasionally, an object does not need to be referenced later. In this case, you can create an object without explicitly assigning it to a variable, as shown below:

   new   Circle(); 

or

 System.out.println(   "Area is "   +   new   Circle(   5   ).getArea()); 


[Page 218]

The former statement creates a Circle object. The latter statement creates a Circle object and invokes its getArea method to return its area. An object created in this way is known as an anonymous object .


7.4.3. Example: Declaring Classes and Creating Objects

Listing 7.1 is a program that declares a circle class. To avoid a naming conflict with several improved versions of the Circle class introduced later in this book, the Circle class in this example is named Circle1 .

The program constructs a circle object with radius 5 and an object with radius 1 and displays the radius and area of each of the two circles. Change the radius of the second object to 100 and display its new radius and area, as shown in Figure 7.4.

Figure 7.4. The program constructs two circles with radii of 5 and 1, and displays their radii and areas.


Listing 7.1. TestCircle1.java
(This item is displayed on pages 218 - 219 in the print version)
 1   public class   TestCircle1 { 2  /** Main method */  3   public static void   main(String[] args) { 4  // Create a circle with radius 5.0  5  Circle1 myCircle =   new   Circle1(   5.0   );  6 System.out.println(   "The area of the circle of radius "   7 +  myCircle.radius  +   " is "   +  myCircle.getArea()  ); 8 9  // Create a circle with radius 1  10  Circle1 yourCircle = new Circle1();  11 System.out.println(   "The area of the circle of radius "   12 + yourCircle.radius +   " is "   + yourCircle.getArea()); 13 14  // Modify circle radius  15  yourCircle.radius = 100;  16 System.out.println(   "The area of the circle of radius "   17 +  yourCircle.radius  +   " is "   +  yourCircle.getArea()  ); 18 } 19 } 20 21  // Define the circle class with two constructors  22   class   Circle1 { 23   double  radius  ; 24 25  /** Construct a circle with radius 1 */  26  Circle1()  { 27 radius =   1   .     ; 28 } 29 30  /** Construct a circle with a specified radius */  31  Circle1(   double  newRadius)   { 32 radius = newRadius; 33 } 

[Page 219]
 34 35  /** Return the area of this circle */  36    double   getArea()  { 37   return   radius * radius * Math.PI; 38 } 39 } 

The program contains two classes. The first class, TestCircle1 , is the main class. Its sole purpose is to test the second class, Circle1 . Every time you run the program, the JVM invokes the main method in the main class.

You can put the two classes into one file, but only one class in the file can be a public class. Furthermore, the public class must have the same name as the file name and the main method must be in a public class. Therefore, the file name is TestCircle1.java if the TestCircle1 and Circle1 classes are both in the same file.

The main class contains the main method (line 3) that creates two objects. The constructor Circle1(5.0) was used to create myCircle with a radius of 5.0 (line 5), and the constructor Circle1() was used to create yourCircle with a radius of 1.0 (line 10).

These two objects (referenced by myCircle and yourCircle ) have different data but share the same methods. Therefore, you can compute their respective areas by using the getArea() method.

To write the getArea method in a procedural programming language like Pascal, you would pass radius as an argument to the method. But in object-oriented programming, radius and getArea are defined in the object. The radius is a data member in the object, which is accessible by the getArea method. In procedural programming languages, data and methods are separated, but in an object-oriented programming language, data and methods are grouped together.

The getArea method is an instance method that is always invoked by an instance in which the radius is specified.

There are many ways to write Java programs. For instance, you can combine the two classes in the example into one, as shown in Listing 7.2.

Listing 7.2. Circle1.java
(This item is displayed on pages 219 - 220 in the print version)
 1    public class   Circle1  { 2  /** Main method */  3    public static void    main(String[] args) { 4  // Create a circle with radius 5.0  5  Circle1 myCircle =   new   Circle1(   5   .     );  6 System.out.println(   "The area of the circle of radius "   7 + myCircle.radius +   " is "   + myCircle.getArea()); 8 9  // Create a circle with radius 1  10  Circle1 yourCircle =   new  Circle1();   11 System.out.println(   "The area of the circle of radius "   12 + yourCircle.radius +   " is "   + yourCircle.getArea()); 13 14  // Modify circle radius  15 yourCircle.radius =   100   ; 16 System.out.println(   "The area of the circle of radius "   17 + yourCircle.radius +   " is "   + yourCircle.getArea()); 18 } 19 20   double   radius; 21 22  /** Construct a circle with radius 1 */  23  Circle1()  { 

[Page 220]
 24 radius =   1.0   ; 25 } 26 27  /** Construct a circle with a specified radius */  28  Circle1(   double   newRadius)  { 29 radius = newRadius; 30 } 31 32  /** Return the area of this circle */  33    double   getArea()  { 34   return   radius * radius * Math.PI; 35 } 36 } 

Since the combined class has a main method, it can be executed by the Java interpreter. The main method creates myCircle as a Circle1 object and then displays radius and finds area in myCircle . This demonstrates that you can test a class by simply adding a main method in the same class.

Caution

Recall that you use Math.methodName(arguments) (e.g., Math.pow(3, 2.5) ) to invoke a method in the Math class. Can you invoke getArea() using Circle1.getArea() ? The answer is no. All the methods in the Math class are static methods, which are defined using the static keyword. However, getArea() is an instance method, and thus non-static. It must be invoked from an object using objectRefVar.methodName(arguments) (e.g., myCircle.getArea() ). More explanations will follow in §7.6, "Static Variables, Constants, and Methods."


Tip

If you use an IDE such as JBuilder, NetBeans, or Eclipse, please refer to Learning Java Effectively with JBuilder/NetBeans/Eclipse in the supplements. This supplement shows you how to use a debugger to inspect objects.


7.4.4. Reference Data Fields and the null Value

The data fields can be of reference types. For example, the following Student class contains a data field name of the String type. String is a predefined Java class.

   class   Student { String name;  // name has default value null    int   age;  // age has default value 0    boolean   isScienceMajor;  // isScienceMajor has default value false    char   gender;  // c has default value '\u0000'  } 

If a data field of a reference type does not reference any object, the data field holds a special Java value, null . null is a literal just like true and false . While true and false are Boolean literals, null is a literal for a reference type.

The default value of a data field is null for a reference type, for a numeric type, false for a boolean type, and '\u0000' for a char type. However, Java assigns no default value to a local variable inside a method. The following code displays the default values of data fields name , age , isScienceMajor , and gender for a Student object:

   class   Test {   public static void   main(String[] args) {  Student student =   new   Student();  

[Page 221]
 System.out.println(   "name? "   +  student.name  ); System.out.println(   "age? "   +  student.age  ); System.out.println(   "isScienceMajor? "   +  student.isScienceMajor  ); System.out.println(   "gender? "   +  student.gender  ); } } 

The following code has a compilation error because local variables x and y are not initialized :

   class   Test {   public static void   main(String[] args) {    int  x;    // x has no default value   String y;   // y has no default value  System.out.println(   "x is "   +  x  ); System.out.println(   "y is "   +  y  ); } } 

Caution

NullPointerException is a common runtime error. It happens when you invoke a method on a reference variable with null value. Make sure you assign an object reference to the variable before invoking the method through the reference variable.


7.4.5. Differences Between Variables of Primitive Types and Reference Types

Every variable represents a memory location that holds a value. When you declare a variable, you are telling the compiler what type of value the variable can hold. For a variable of a primitive type, the value is of the primitive type. For a variable of a reference type, the value is a reference to where an object is located. For example, as shown in Figure 7.5, the value of int variable i is int value 1 , and the value of Circle object c holds a reference to where the contents of the Circle object are stored in the memory.

Figure 7.5. A variable of a primitive type holds a value of the primitive type, and a variable of a reference type holds a reference to where an object is stored in the memory.


When you assign one variable to another, the other variable is set to the same value. For a variable of a primitive type, the real value of one variable is assigned to the other variable. For a variable of a reference type, the reference of one variable is assigned to the other variable. As shown in Figure 7.6, the assignment statement i = j copies the contents of j into i for primitive variables. As shown in Figure 7.7, the assignment statement c1 = c2 copies the reference of c2 into c1 for reference variables. After the assignment, variables c1 and c2 refer to the same object.


[Page 222]
Figure 7.6. Primitive variable j is copied to variable i .


Figure 7.7. Reference variable c2 is copied to variable c1 .


Note

As shown in Figure 7.7, after the assignment statement c1 = c2 , c1 points to the same object referenced by c2 . The object previously referenced by c1 is no longer useful and therefore is now known as garbage . Garbage occupies memory space. The JVM detects garbage and automatically reclaims the space it occupies. This process is called garbage collection .


Tip

If you know that an object is no longer needed, you can explicitly assign null to a reference variable for the object. The JVM will automatically collect the space if the object is not referenced by any reference variable.


 


Introduction to Java Programming-Comprehensive Version
Introduction to Java Programming-Comprehensive Version (6th Edition)
ISBN: B000ONFLUM
EAN: N/A
Year: 2004
Pages: 503

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net