英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论