鉴于以下代码段:
class SuperClass {
SuperClass () {
foo();
}
public void foo() {
System.out.println("In SuperClass foo");
}
}
public class SubClass extends SuperClass {
private String str;
SubClass() {
str = "SubClass";
}
public void foo () {
System.out.println("In SubClass foo value " + str.toLowerCase());
}
public static void main(String[] args) {
SuperClass ref = new SubClass();
ref.foo();
}
}
此代码抛出NPE,因为在调用foo()时,它在SuperClass构造函数中实际调用SubClass foo()并抛出NPE。我想知道究竟什么时候在这里创建了SubClass对象,因为我们仍然在构造函数中初始化SubClass的成员变量,那么为什么在这里发生了重写?
答案 0 :(得分:0)
作为链接:https://www.geeksforgeeks.org/g-fact-67/
在Java中,在派生类构造函数中自动调用没有参数的基类构造函数。
创建ref时,它有地址:SubClass @ c2e1f26。它是SubClass。
所以。当在SuperClass()构造中调用foo时,它会搜索SubClass中的foo()并执行它。
更新关注问题
- 我们应该记住.SuperClass()构造函数是调用第一个SubClass()构造函数。所以当属性str没有初始化时。
答案 1 :(得分:0)
it will first call the subclass constructor then subclass to the superclass and then superclass to the object and the execution returns to the superclass then it will start printing.
the first statement will print
在SuperClass foo
在SubClass foo值子类
中
but since the str is not followed up then it will obviously throw the null pointer exception.
答案 2 :(得分:0)
初始化Subclass
时,首先调用Superclass
构造函数。需要在子类之前构造超类(更一般)(更具体)。有道理,对吧?
现在,在超类的构造函数中,调用了foo
。猜猜哪个 foo
被调用?子类的foo
!这是因为您正在创建一个Subclass
对象,因此您调用的每个实例方法都将调用子类的实现,因为polymorphism。
因此调用了子类的foo
并尝试打印str.toLowerCase()
。请注意,由于尚未调用子类的构造函数,因此str
未初始化,因此初始值为nil
,抛出NullPointerException
。
如果子类的foo
方法成功运行,那么超类的构造函数将返回,并且子类的构造函数最终将被调用。
当天的教训:不要在非final类的构造函数中调用非final方法。