Why NullPointerException?

2022-09-01 22:56:47

I have a abstract class and a derived class. Look at provided code:-

public abstract class Parent{
    public Parent(){
        init();
    }

    public abstract void init();    
}



public class Child extends Parent{
    private String mTitle = null;

    public Child(){
        super();
        System.out.println(mTitle.toString());
    }       

    public void init(){
        mTitle = "It' a test";
    }    
}

When I will execute the above code it will throw NullPointerException on printing the value of mTitle. If you check the code in constructor of parent I have called the the abstract method which will called the init method of derived class, In abstract method I have initialize the value of mTitle value as ="It's a test";

After calling parent constructor derived class have to call the System.out.println.

If it is doing in that way then why it is throwing NullPointerException.

But, If I just leave the assignment of mTitle it will not throw Exception like:-

private String mTitle;

If initialization of variable occur on calling of the contruct of class and we know by default global object have initialize to null. But in this case it will not throw Exception.


答案 1

As in JLS §12.5 (Creation of New Class Instances) the following procedure is used when an instance is created:

  1. Assign the arguments for the constructor to newly created parameter variables for this constructor invocation.

  2. If this constructor begins with an explicit constructor invocation (§8.8.7.1) of another constructor in the same class (using this), then evaluate the arguments and process that constructor invocation recursively using these same five steps. If that constructor invocation completes abruptly, then this procedure completes abruptly for the same reason; otherwise, continue with step 5.

  3. This constructor does not begin with an explicit constructor invocation of another constructor in the same class (using this). If this constructor is for a class other than Object, then this constructor will begin with an explicit or implicit invocation of a superclass constructor (using super). Evaluate the arguments and process that superclass constructor invocation recursively using these same five steps. If that constructor invocation completes abruptly, then this procedure completes abruptly for the same reason. Otherwise, continue with step 4.

  4. Execute the instance initializers and instance variable initializers for this class, assigning the values of instance variable initializers to the corresponding instance variables, in the left-to-right order in which they appear textually in the source code for the class. If execution of any of these initializers results in an exception, then no further initializers are processed and this procedure completes abruptly with that same exception. Otherwise, continue with step 5.

  5. Execute the rest of the body of this constructor. If that execution completes abruptly, then this procedure completes abruptly for the same reason. Otherwise, this procedure completes normally.

That means your call to and the subsequent call to the overridden method are both done before the instance variable is initialized with which discards the outcome of the method and overwrites any value being assigned to with the value.super()init()nullinitmTitlenull

This leads to the following Golden Rule: Never call non-final, non-private methods in a constructor!


答案 2

According to Section 12.5 of the JLS, the superclass constructor will run before the initialiser for , which means that it will be set back to after it is set to .mTitlenull"It's a test"


推荐