If only one object is created during inheritance then what is super keyword referencing to?



In the following code, what is super keyword referencing to?

class A {
    int i1 = 10;
    A() {
        System.out.println("class A");
    }
}
class B extends A {
    int i2 = super.i1;
    B() {
        System.out.println("class B");
    }
}
class C extends B {
    int i3 = super.i2;
    
    public static void main(String args[]) {
        C c = new C();
        System.out.println(c.i3);
    }
}

If no objects/instances of super class are created, then what is super keyword referencing to as it is a reference variable and supposed to reference super class instance?

Answer

Note that super is a bit different from this, in that super is not a primary expression. In fact, super is not an expression at all. So it makes little sense to say that super itself refers to anything. Note that you can’t do:

SomeType foo = super;

What does make sense, are these (not an exhaustive list of everything that involves super):

  • superclass constructor calls of the form super(...);
  • field access of the form super.identifier
  • method call of the form super.identifier(...)

Those forms all refer to different things, but the word super itself has no single meaning, unless you are satisfied with “something to do with the superclass”.

Specifically in this question, you are asking about field access. This is described in section 15.11.2 of the language specification.

The form super.Identifier refers to the field named Identifier of the current object, but with the current object viewed as an instance of the superclass of the current class.

For i1, since B inherits from A, i1 will refer to the same field even if you view the current object as a B, so it doesn’t matter what class you view the current object as. Whether it is super.i1, or this.i1, or just i1, doesn’t make a difference. The difference is more apparent when you redeclare i1 in B:

class A { 
    int i1 = 10;
}
class B extends A { 
    int i1 = 20; 
    int i2 = super.i1;
}

i2 will get the value of 10, rather than 20, because you viewed the current object as an A. Note that in this case, an instance of B gets two fields called i1, one inherited from A, and one declared in B. Viewing the object “as an A” will let you see the one inherited from A, otherwise it is hidden.



Source: stackoverflow