私有变量突然变为 null。

huangapple go评论86阅读模式
英文:

private variable is suddenly null

问题

假设我们有一个类:

public class MyClass extends AbstractClass {

    private AnotherObject ao = null;

    public MyClass() {
        super();
    }

    @Override
    protected void init() {
        ao = new AnotherObject();
        if (ao != null) {
            log.info("NOT NULL");
        }
    }

    @Override
    protected void doSomething() {
        if (ao == null) {
            log.info("It is NULL.");
        }
        ao.doIt(); //NullPointerException here
    }
}

以及相应的抽象类:

public class AbstractClass implements Runnable {
    Thread myThread = null;
    
    AbstractClass() {
        init();
        myThread = new Thread(this, "ThreadName");
        myThread.start();
    }

    public void run() {
        while(true) {
            doSomething();
            Thread.sleep(1000);
        }
    }

    protected abstract void init();
    protected abstract void doSomething();
}

MyClass 的构造函数调用了父类的构造函数,父类的构造函数调用了 init() 方法。这个 init 方法初始化了 ao 变量,因此日志显示这个 ao 对象不是 null。

在此之后,父类的构造函数创建了一个线程,这个线程将执行 while 循环,调用了 doSomething() 方法。在这个被覆写的方法中,使用了 ao 对象,但是这个 ao 对象突然变成了 null。

有人可以解释一下为什么 ao 对象被设置,然后突然变成 null 吗?

英文:

Let's say we have a class:

public class MyClass extends AbstractClass {

    private AnotherObject ao = null;

    public MyClass() {
        super();
    }

    @Override
    protected void init() {
        ao = new AnotherObject();
        if (ao != null) {
            log.info("NOT NULL");
        }
    }

    @Override
    protected void doSomething() {
        if (ao == null) {
            log.info("It is NULL.");
        }
        ao.doIt(); //NullPointerException here
    }
}

And the corresponding abstract class:

public class AbstractClass implements Runnable {
    Thread myThread = null;
    
    AbstractClass () {
        init();
        myThread = new Thread(this, "ThreadName");
        myThread.start();
    }

    public void run() {
        while(true) {
            doSomething();
            Thread.sleep(1000);
        }
    }

    protected abstract void init();
    protected abstract void doSomething();
}

The constructor of MyClass calls the parent's constructor and the parent's constructor calls the init() method. This init method initializes the ao variable and therefore the log shows, that this ao object is NOT null.

After this, the parent's constructor creates a thread and this thread will execute the while loop, which calls doSomething(). In this overridden method, the ao object is used, but this ao object is suddenly null.

Can somebody explain me the ao object is set and then suddenly it is null?

答案1

得分: 10

private AnotherObject ao = null;

`= null;` 删除

你是通过在父构造函数中调用的方法进行初始化的但之后又执行了将其初始化为 null 的操作

为了更清楚这段代码

    private AnotherObject ao = null;

    public MyClass() {
        super();
    }

与这段代码相同

    private AnotherObject ao;

    public MyClass() {
        super();
    }
英文:
private AnotherObject ao = null;

Remove the = null;.

You are initializing it by the methods invoked in the super constructor, but the initializer to null is then executed afterwards.

To be more clear, this:

    private AnotherObject ao = null;

    public MyClass() {
        super();
    }

is identical to this:

    private AnotherObject ao;

    public MyClass() {
        super();
        ao = null;
    }

答案2

得分: 2

根据这里所述,super 构造函数在字段初始化程序之前运行(即 private AnotherObject ao = null;)。

因此,super(); 调用会先运行,将 ao 设置为非空,然后返回,然后 private AnotherObject ao = null; 会运行,将 ao 再次设置为 null。

这就是为什么不应在构造函数中调用可以在子类中被覆盖的方法。因为在那时,this 还没有完全初始化。

英文:

According to here, the super constructor is run before the field initialisers (i.e. private AnotherObject ao = null;).

Therefore, the super(); call gets run, sets ao to non-null, returns, and then private AnotherObject ao = null; gets run, setting ao to null again.

This is why you should not call methods that can be overridden in subclasses in a constructor. Because at that point, this has not been fully initialised.

huangapple
  • 本文由 发表于 2020年8月17日 16:42:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/63447449.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定