基类:
public class Base {
private String baseMessage = "Hello!";
public Base() {
printMessage();
}
public void printMessage() {
System.out.println(baseMessage.toString());
}
}
派生类:
public class Derived extends Base {
private String derivedMessage = "World!";
public Derived () {
super();
}
@Override
public void printMessage() {
super.printMessage();
System.out.println(derivedMessage.toString());
}
public static void main(String[] args) {
// new Base();
new Derived();
}
}
当我跑步时
new Base();
我得到了预期的输出:
Hello!
当我跑步
new Derived();
我得到了
Hello!
Hello!
然后是NullPointerException。这对我来说似乎有点奇怪。我不知道为什么它打印出来然后抛出一个nullpointerexception,而不是直接抛出它。也许是Eclipse,我不知道。
这里的基本概念是什么?
答案 0 :(得分:5)
在您阅读本文之前,请阅读
子类构造函数的主体被编译为类似
的内容public Derived () {
super();
initializeInstanceFields();
// all instance fields are initialized either to their default value
// or with their initialization expression
}
换句话说,当Derived#printMessage()
由于super
构造函数的多态性而被调用时,Derived.derivedMessage
仍然是null
。
这是一步一步:
new Derived();
调用Derived
构造函数
public Derived () {
super();
}
调用super
构造函数
public Base() {
printMessage();
}
此处,在printMessage()
之前,这个班级'实例字段已初始化,因此baseMessage
获取"Hello!"
的值。调用printMessage()
时,因为this
是Derived
对象而Derived
会覆盖这些方法,所以会调用其实现。
@Override
public void printMessage() {
super.printMessage();
System.out.println(derivedMessage.toString());
}
这会调用super
实现
public void printMessage() {
System.out.println(baseMessage.toString());
}
打印
Hellow!
该方法返回Derived#printMessage
并尝试在toString()
上调用derivedMessaged
,但正如我之前解释的那样,derivedMessage
没有&{39}。尚未初始化,因此它是null
。取消引用null
会导致NullPointerException
。
这就是为什么你不从构造函数调用可覆盖的方法。