Andreas Solymosi

Casting this in Java

This is a frequent problem: how can we reach covered attributes and overloaded methods in a super-superclass? If an attribute is not covered or a method is not overloaded, they can be reached by name. For attributes and methods of the superclass is super. available. But there is no super super.super. – there is no access to the super-superclass.

Fortunately you can convert (cast) this and reach the attributes of the super-superclass:

public class A {
  protected String attribute = "A";
  protected void method() {
     System.out.print(attribute); }  } // as expected: A

class B extends A {
  protected String attribute = "B"; // covers A.attribute
  protected void method() {
     System.out.print(attribute); // as expected: B
     System.out.print(super.attribute); // as expected: A
     super.method(); } } // as expected: A

class C extends B {
  protected String attribute = "C"; // covers B.attribute
  protected void method() {
     System.out.print(attribute); // as expected: C
     System.out.print(super.attribute); // as expected: B
     System.out.print(((A)this).attribute); // A.attribute!!!
     super.method(); // B.method() -> BAA
     try {
       ((A)this).method(); /* A.method()? no, C.method() -> endless recursion */
     } catch (StackOverflowError e) {
       System.out.println("StackOverflowError"); } }

  public static void main(String[] args) {
     System.out.println("expected: A");
     new A().method(); // A
     System.out.println();
     System.out.println("expected: BAA");
     new B().method(); // BAA
     System.out.println();
     System.out.println("expected: CBABAA");
     new C().method(); } } // CBABAA, rekursive

In this example is A.attribute covered by B.attribute, and this one is covered by C.attribute. From B you can reach A.attribute (as ususal) by super.attribute. From C is this possible by the converted this: ((A)this).attribute.

Unfortunately this doesn't work for methods: ((A)this).methode(); in try block doesn't call A.method() but C.method() and ends in an endless recursion. The reason is following.

Type conversion is done by the compiler: it allows access from a reference (here: this) of a "wrong" type to an attribute or a method. Whether this access is correct (whether an object of the target type is referenced), is checked by the interpreter at run time and if not, ClassCastException is thrown. The selection of a method being called happens however not at compile time but at run time by the interpreter in accordance to the type of the referenced object (this is called "polymorphismus" and is implemented by "late binding"). The conversion changes only the type of the reference (for the compiler), not the type of the referenced object (for the interpreter). This is why even a converted this calls always the method from the own class (here C) and not from the class of the target type (here A). A method from the super-superclass can be called only through an object of the super-superclass:

     new A().method();

super is a reference to the superclass-part of the object. However, Java's syntax doesn't allow the conversion of super (in contrary to this):

     ((A)super).method(); // syntax error


Version: 25. January 2012

© Prof. Solymosi, 2011, Beuth-Hochschule für Technik Berlin, Faculty for Computer Science and Media

solymosibht-berlin.de