0

I have following questions about the super keyword in java:

I have a code below with classes:

  • A Extends no class contains integer variable i
  • B Extends class A contains integer variable i
  • C Extends class B contains integer variable i

     class A {
        int i = 20;
    
        A() {
            System.out.println("I am in constructor of the parent class");
        }
    }
    
    class B extends A {
        int i = 30;
    
        B() {
            System.out.println("I am in constructor of the subclass");
        }
    }
    
    class C extends B {
        int i = 40;
    
        C() {
            System.out.println("I am in constructor of the main class");
        }
    
        void display() {
            System.out.println(i);
            System.out.println(super.i);
            /*
             * My first thoughts to access the third variable 'i'
             * inherited indirectly to this class by 'class A'.
             * I thought that it would print 20 :(.
               System.out.println(super.super.i);
             */ 
        }
    
        public static void main(String[] argue) {
            C obj2 = new C(); 
            obj2.display();
        }
    }
    
    1. Now as class B inherits class A so it must have two integer variables i. Class C inherits class B so it will have two integer variables from B and one defined in itself.

Now I can print the inherited super class variable i in class C through the display method and of course the variable i defined in class C itself. The question is how to print the third i which has the value "20".

I know I can define a method in the class B that returns super.i; and call it through its object in class A that will print the third variable i and I also known that I can create an object of class A, but is there any other way by using super or any other thing to directly access the third variable in the class C.

Also the output is:

      I am in constructor of the parent class
      I am in constructor of the subclass
      I am in constructor of the main class
      40
      30
  1. why like the this keyword the super keyword cannot be used inside static methods?

  2. why is the super class constructor called to initialize the inherited variables of a subclass? This doesn't make any sense because if a class extends another class the variables and methods will be like they were locally declared in the class in other words its own members. So why can't the constructor of the subclass initialize those inherited members and has to call the super class constructor to initialize them.

1
  • Try changing A.i to private. This shouldn't cause a problem, the code should compile and work just as before. But how would then Bs constructor initialise it?
    – biziclop
    Dec 1, 2015 at 15:08

3 Answers 3

3

In addition to all the above, consider the following scenario:

  • You start out with these two classes.

     class A {
        int i = 20;
    
        A() {
            System.out.println("I am in constructor of the parent class");
        }
    }
    
    class B extends A {
        int i = 30;
    
        B() {
            System.out.println("I am in constructor of the subclass");
        }
    }
    
  • You compile both classes, it creates two class files: A.class and B.class

  • Now you change your mind and rewrite A:

     class A {
        int i = 10;
    
        A() {
            System.out.println("I am in constructor of the parent class");
        }
    }
    
  • You recompile A, so you get a new A.class, which you replace the old A.class with

Now the question is: how would B know that As initialisation code has changed? You haven't recompiled B, nor should you be required to do so. After all, B may already be packaged up in a different jar, maybe even in a different product you have no control over.*

The only reasonable way to support this case is for Bs constructor to start with calling As constructor and let A initialise itself.

*This may sound far-fetched at first, but this is exactly what happens when internal implementation details of JDK classes are changed. All the previously compiled Java applications in the world should run seamlessly with the new JDK.

1
  • Thankyou @ biziclop, you have given a satisfactory answer to point # 03.Much obliged :).I am sorry i can't up-vote your answer because of 14 reputation. Dec 2, 2015 at 3:15
4

Much of this is spelled out in the JLS section 15.11:

15.11.2 Accessing Superclass Members using super
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.

The key word there is of the current object. If there is no current object, such as the case with a static method, you can't user the super method.


When it comes to the constructor, the super class is responsible for initializing its fields. This is necessary because there may be private fields within the super class that a subclass has no access to.

Furthermore, requiring the subclass to instantiate the state of the super class may require the subclass to have more information than necessary and also requires a tighter coupling between superclass and subclass than is desirable - any change to the fields in the superclass would require a change in all the subclasses. This is a bad thing.

Thus, you prevent this bad thing from happening by having the subclass call the constructor of the superclass when it is created.

4
  • Thank you @MichaelT.Does that mean i cannot access the third variable "i" inherited to the class C by Class B.I mean as class A will have three variables named "i", i can access two of them using just "i" and "super.i" but what about the third one? Dec 1, 2015 at 4:58
  • @WithASpiRIT Try A.this.i, it might work. That sort of syntax is used when you want to access an outer class from an inner class.
    – Darsstar
    Dec 1, 2015 at 8:18
  • @MichaelT This doesn't work because you cannot access non-static fields with reference to their class name. Dec 2, 2015 at 3:06
  • Thankyou for your response @MichaelT.You have helped a lot. Dec 2, 2015 at 3:16
1

Your code is incomplete - here's what Java added for you:

class A extends Object { /* <-- Added */ 
    int i = 20;
    A() {
        super(); /* <-- Added */ 
        System.out.println("I am in constructor of the parent class");
    }
}

And your other classes do just the same.

All classes extend some other class, even if it's "just" Object.

"super" refers to the super-class of the current instance but Static methods have no instance; they're just lumps of code that are "attached" to a class, but make no reference to any data held within the instance itself. If this were a .Net question, I'd point you to the Split() and Join() methods on the String class; the [instance] Split method breaks up the current value held inside the String object but the [static] Join method takes both delimiter and [array] value as arguments and puts them together.

Constructors are inherently private in their action. Their job is to ready the object itself to go to work, without any reference to its super class or any subclass (about which it should know nothing at all). Instantiation runs all the way up the super-class "chain", all the way to Object, and executes the constructor on each class on the way "back down".

2
  • Thankyou @ Phill W, you have given a satisfactory answer to point # 02.Much obliged :).I am sorry i can't up-vote your answer because of 14 reputation. Dec 2, 2015 at 3:15
  • Each method on your class has an implicit this pointer as the first argument, which the compiler hides. The method accesses its members through that pointer. Static methods do not have a this pointer, they access static members through an implicit class reference (e.g. MyClass.x). Generally we omit these implicit references which is why beginners sometimes have a difficult time understanding how class and object state/methods are truly accessed.
    – user22815
    Dec 2, 2015 at 4:23

Not the answer you're looking for? Browse other questions tagged or ask your own question.