Java - Subclass calls supers constructor which calls subclass method instead of its own
constructor, inheritance, java, methods, overriding
Solution
The `NullPointerException` occurs because when you construct an instance of B, the parent constructor (in A) is invoked. This constructor calls the `f()` method but since the actual type of the object is B, the overridden `f()` method in B is invoked.
@Override
public void f() {
//Anything that access o.
o.hashCode(); //Throws NullPointerException as o has not been initialised yet
super.f();
}
The lesson here is never to call a method in a constructor which can be overridden by a subclass.
Problem
I'll start with a code example: ``` class A { public A() { f(); //When accessed through super() call this does not call A.f() as I had expected. } public void f() {} //I expect this to be called from the constructor. } class B extends A { private Object o; public B() { super(); o = new Object(); //Note, created after super() call. } @Override public void f() { //Anything that access o. o.hashCode(); //Throws NullPointerException. super.f(); } } public class Init { public static void main(String[] args) { B b = new B(); } } ``` This program throws a `NullPointerException`. When the object b enters the constructor of its superclass `A` and makes a call to the method `f()` which is overridden by the class B `B.f()` is called, instead of `A.f()` which I would have expected. I thought a superclass wasn't supposed to know if it was subclassed or not but surely this can be used by a class to tell if it's been subclassed or not? What's the reason behind this? Is there any workaround if I really want `A.f()` to be called instead of `B.f()`? Thanks in advance. Follow up question: Thanks for the answers. I now understand why it is like it is, but here's a follow up question. Perhaps I'm mistaken but a principle of subtyping is that the supertype should not know that it's been subtyped. This "mechanism" lets a class know if it's been subclassed or not. Consider this code example: ``` class A { private boolean isSubclassed = true; public A() { f(); //A.f() unsets the isSubclassed flag, B.f() does not. if(this.isSubclassed) { System.out.println("I'm subclassed."); } else { System.out.println("I'm not subclassed."); } } public void f() { this.isSubclassed = false; } } class B extends A { public B() { super(); } @Override public void f() {} } public class Init { public static void main(String[] args) { new B(); //Subclass. new A(); } } ``` The output of this program is: ``` I'm subclassed. I'm not subclassed. ``` Here `A` knows it's been subclassed. It's unkown by whom but that doesn't matter. How is this explained? Am I misinformed?