CHAPTER 15: Expressions Previous
Previous
Java Language
Java Language
Index
Index
Next
Next

15.10 Field Access Expressions

15.10.1 Field Access Using a Primary , 15.10.2 Accessing Superclass Members using super

A field access expression may access a field of an object or array, a reference to which is the value of either an expression or the special keyword super . (It is also possible to refer to a field of the current instance or current class by using a simple name; see S15.13.1.)


FieldAccess:

	Primary . Identifier

	super . Identifier

The meaning of a field access expression is determined using the same rules as for qualified names (S6.6), but limited by the fact that an expression cannot denote a package, class type, or interface type.


15.10.1 Field Access Using a Primary

The type of the Primary must be a reference type T, or a compile-time error occurs. The meaning of the field access expression is determined as follows:

Note, specifically, that only the type of the Primary expression, not the class of the actual object referred to at run time, is used in determining which field to use.

Thus, the example:

class S { int x = 0; }
class T extends S { int x = 1; }
class Test {
	public static void main(String[] args) {


		T t = new T();
		System.out.println("t.x=" + t.x + when("t", t));

		S s = new S();
		System.out.println("s.x=" + s.x + when("s", s));

		s = t;
		System.out.println("s.x=" + s.x + when("s", s));

	}


	static String when(String name, Object t) {
		return " when " + name + " holds a "
			+ t.getClass() + " at run time.";
	}
}

produces the output:


t.x=1 when t holds a class T at run time.
s.x=0 when s holds a class S at run time.
s.x=0 when s holds a class T at run time.

The last line shows that, indeed, the field that is accessed does not depend on the run-time class of the referenced object; even if s holds a reference to an object of class T , the expression s.x refers to the x field of class S , because the type of the expression s is S . Objects of class T contain two fields named x , one for class T and one for its superclass S .

This lack of dynamic lookup for field accesses allows Java to run efficiently with straightforward implementations. The power of late binding and overriding is available in Java, but only when instance methods are used. Consider the same example using instance methods to access the fields:

class S { int x = 0; int z() { return x; } }
class T extends S { int x = 1; int z() { return x; } }
class Test {


	public static void main(String[] args) {
		T t = new T();
		System.out.println("t.z()=" + t.z() + when("t", t));
		S s = new S();
		System.out.println("s.z()=" + s.z() + when("s", s));
		s = t;
		System.out.println("s.z()=" + s.z() + when("s", s));
	}

	static String when(String name, Object t) {
		return " when " + name + " holds a "
			+ t.getClass() + " at run time.";
	}
}

Now the output is:


t.z()=1 when t holds a class T at run time.
s.z()=0 when s holds a class S at run time.
s.z()=1 when s holds a class T at run time.

The last line shows that, indeed, the method that is accessed does depend on the run-time class of referenced object; when s holds a reference to an object of class T , the expression s.z() refers to the z method of class T , despite the fact that the type of the expression s is S . Method z of class T overrides method z of class S .

The following example demonstrates that a null reference may be used to access a class (static ) variable without causing an exception:


class Test {
	static String mountain = "Chocorua";

	static Test favorite(){
		System.out.print("Mount ");
		return null;
	}

	public static void main(String[] args) {
		System.out.println(favorite().mountain);
	}
}

It compiles, executes, and prints:

Mount Chocorua

Even though the result of favorite() is null , a NullPointerException is not thrown. That "Mount " is printed demonstrates that the Primary expression is indeed fully evaluated at run time, despite the fact that only its type, not its value, is used to determine which field to access (because the field mountain is static ).


15.10.2 Accessing Superclass Members using super

The special form using the keyword super is valid only in an instance method or constructor, or in the initializer of an instance variable of a class; these are exactly the same situations in which the keyword this may be used (S15.7.2). The form involving super may not be used anywhere in the class Object , since Object has no superclass; if super appears in class Object , then a compile-time error results.

Suppose that a field access expression super. name appears within class C, and the immediate superclass of C is class S. Then super. name is treated exactly as if it had been the expression (( S)this). name; thus, it refers to the field named name of the current object, but with the current object viewed as an instance of the superclass. Thus it can access the field named name that is visible in class S, even if that field is hidden by a declaration of a field named name in class C.

The use of super is demonstrated by the following example:


interface I { int x = 0; }
class T1 implements I { int x = 1; }
class T2 extends T1 { int x = 2; }
class T3 extends T2 {
	int x = 3;
	void test() {
		System.out.println("x=\t\t"+x);
		System.out.println("super.x=\t\t"+super.x);
		System.out.println("((T2)this).x=\t"+((T2)this).x);
		System.out.println("((T1)this).x=\t"+((T1)this).x);
		System.out.println("((I)this).x=\t"+((I)this).x);
	}
}
class Test {
	public static void main(String[] args) {
		new T3().test();
	}
}

which produces the output:


x=					3
super.x=					2
((T2)this).x=					2
((T1)this).x=					1
((I)this).x=					0

Within class T3 , the expression super.x is treated exactly as if it were:

((T2)this).x



Top© 1996 Sun Microsystems, Inc. All rights reserved.