Java – Overriding – Access to Members with Reference Reassignment

javamethodsreference

I have recently been moving through a couple of books in order to teach myself Java and have, fortunately, mostly due to luck, encountered very few difficulties. That has just changed.

I read a section on the following under inheritance and the whole superclass subclass setup

  • When a new superclass object is created, it is, like all objects, assigned a reference (superReference in this example)

  • If a new subclass object (with the defining subclass extending the superclass) is created, and then the superReference reference is set to refer to that instead of the original object, it is my understanding that, since the reference is made for a superclass, only members defined by the superclass may be accessed from the subclass.

First – is this correct?

Second:
If I am overriding a method and therefore have one in the super and one in the sub, and I create a superclass object and then assign its reference, as I did above, to a subclass object, by the principle called something like Dynamic Method Dispatch, a called overridden method should default to accessing the subclass method right?

Well, my question is:

If a reference to a superclass-object is retooled for a subclass-object and will deny direct object.member access to subclass-defined members, only supporting superclass-defined members, how can, if a superclass reference is retooled for a subclass object, an overridden method apply to the subclass-object if access is limited by the superclass-originated-reference

Best Answer

If you look at the Java Language Specification (http://docs.oracle.com/javase/specs/) you will find a distinction between the static type and the dynamic type of object references.

The static type of any reference refers to the type declared in your program at development time.

The dynamic type of the reference refers to the type of object which is actually stored at the reference address at runtime.

So if you have a simple hierarchy, where A is the superclass and B is a subclass of A.

class A {
  public String a = "super";
  void m() {...}
}

class B extends A {
  public String a = "sub";
  @Override
  void m() {...}
}

A refA = new A();
A refB = new B();
B refB2 = new B();
refA.m();
refB.m();
System.out.println(refA.a);
System.out.println(refB.a);
System.out.println(refB2.a);

For example, refB's static type is A but its dynamic type is B. What does this imply at runtime?

  1. Instance variables are statically bound, i.e. you can only access the instance variables of the static type, so the first two println() statements will print "super", since A is the static type of refA and refB. The last println() statement will in contrast print "sub", because in this case B is the static type.
  2. Methods are dynamically bound, i.e. the invoked method is first searched in the dynamic type of the reference and if it isn't found, the class hierarchy is traversed up until a definition of the overriden method is found (this mechanism is called dynamic dispatch). This means that in case refA.m() method void m() of A is invoked and in case refB.m(), void m() of B is invoked.