为什么NullPointerException?

Avi*_*Avi 23 java inheritance exception abstract

我有一个抽象类和派生类.看看提供的代码: -

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";
    }    
}
Run Code Online (Sandbox Code Playgroud)

当我执行上面的代码时,它将在打印mTitle的值时抛出NullPointerException.如果检查父构造函数中的代码,我调用了抽象方法,它将调用派生类的init方法,在抽象方法中,我将mTitle值的值初始化为="它是一个测试";

在调用父构造函数派生类之后必须调用System.out.println.

如果它以这种方式进行,那么为什么它会抛出NullPointerException.

但是,如果我只是离开mTitle的赋值它不会抛出异常,如: -

private String mTitle;
Run Code Online (Sandbox Code Playgroud)

如果在调用类的构造时发生变量的初始化,并且我们知道默认情况下全局对象已初始化为null.但在这种情况下,它不会抛出异常.

See*_*ose 26

JLS§12.5(创建新类实例)一样,在创建实例时使用以下过程:

  1. 将构造函数的参数分配给此构造函数调用的新创建的参数变量.

  2. 如果此构造函数以同一个类中的另一个构造函数的显式构造函数调用(第8.8.7.1节)开头(使用此方法),则使用这五个相同步骤计算参数并以递归方式处理该构造函数调用.如果该构造函数调用突然完成,则此过程突然完成,原因相同; 否则,继续步骤5.

  3. 此构造函数不以同一个类中的另一个构造函数的显式构造函数调用开头(使用此方法).如果此构造函数用于Object以外的类,则此构造函数将以超类构造函数的显式或隐式调用开始(使用super).使用这五个相同的步骤评估参数并递归处理超类构造函数调用.如果该构造函数调用突然完成,则此过程突然完成,原因相同.否则,继续执行步骤4.

  4. 为此类执行实例初始值设定项和实例变量初始值设定项,将实例变量初始值设定项的值按从左到右的顺序分配给相应的实例变量,在这些顺序中,它们以文本方式出现在类的源代码中.如果执行任何这些初始值设定项导致异常,则不会处理其他初始化程序,并且此过程会突然完成同样的异常.否则,继续步骤5.

  5. 执行此构造函数的其余部分.如果执行突然完成,则此过程突然完成,原因相同.否则,此过程正常完成.

这意味着您super()对重写init()方法的调用和后续调用都是初始化实例变量之前完成的,null它会丢弃init方法的结果并覆盖赋值给mTitlenull值的任何值.

这导致以下黄金法则:永远不要在构造函数中调用非final,非私有方法!


Daw*_*ica 13

根据JLS的12.5节,超类构造函数将在初始化器之前运行mTitle,这意味着它将在设置为null之后被设置回"It's a test".


归档时间:

查看次数:

1968 次

最近记录:

10 年,10 月 前