NullPointerException : Overriding constructor call

2019-02-27 01:57发布

问题:

I've this code snippet:

class Base {
    public Base() {
        method();
    }

    void method() {
        System.out.println("In Base");
    }
}

class Derived extends Base {
    private String bar;

    public Derived() {
        bar="bar";
    }

    public void method() {
        System.out.println(bar.length());
    }

    public static void main(String[] args) {
        Base base=new Derived();
        base.method();
    }
}

On executing the code I got an exception:

Exception in thread "main" java.lang.NullPointerException
    at Derived.method(Main.java:22)
    at Base.<init>(Main.java:5)
    at Derived.<init>(Main.java:17)
    at Derived.main(Main.java:27)

I'm unable to understand why there is NullPointerException and the stackTrace of the exception. Anyone could help me to understand?

You can check the code here.

回答1:

new Derived() creates a Derived object, which implies calling its super class constructor first, which in turn calls method - but you have overriden method so it is the child version of that method which is called. In that method, you call bar.length which has not been initialised yet.

Conclusion: it is almost never a good idea to call an overridable method in a constructor.



回答2:

The code you have given is an antipattern. We should never invoke a method handling fields from a constructor for a simple reason that it might create unexpected results.

From your code, your are trying to initialize a field called bar in the Derived constructor. Now when you say Base b = new Derived(), the call happens in following fashion

  1. Base static initializer -- If you have
  2. Derived Static Initializer -- If you have

  3. Base block initializer -- If you have

  4. Base Constructor --> this is the place you are calling method()

  5. Derived Block initializer -- If you have

  6. Derived constructor --> this is the place where you are initializing bar

Now due to run time polymorphism, in to No. 4, when the Derived's method() gets called, the bar is not yet initialized to the value "bar" (since initialization happens at No. 6) , the NPE occurs