我将从一个代码示例开始:
class A {
public A() {
f(); //When accessed through super() call this does not call A.f() as I had expected.
}
public void f() {} //I expect this to be called from the constructor.
}
class B extends A {
private Object o;
public B() {
super();
o = new Object(); //Note, created after super() call.
}
@Override
public void f() {
//Anything that access o.
o.hashCode(); //Throws NullPointerException.
super.f();
}
}
public class Init {
public static void main(String[] args) {
B b = new B();
}
}
这个程序抛出一个NullPointerException
。当对象b进入其超类的构造函数时A
并调用该方法f()
被 B 类覆盖B.f()
被称为,而不是A.f()
这是我所期望的。
我认为超类不应该知道它是否被子类化,但是类肯定可以使用它来判断它是否被子类化?这背后的原因是什么?如果我真的想要的话有什么解决办法吗A.f()
被调用而不是B.f()
?
提前致谢。
跟进问题:
感谢您的回答。我现在明白为什么会这样,但这里有一个后续问题。也许我错了,但子类型化的一个原则是超类型不应该知道它已被子类型化。这种“机制”让类知道它是否已被子类化。考虑这个代码示例:
class A {
private boolean isSubclassed = true;
public A() {
f(); //A.f() unsets the isSubclassed flag, B.f() does not.
if(this.isSubclassed) {
System.out.println("I'm subclassed.");
} else {
System.out.println("I'm not subclassed.");
}
}
public void f() {
this.isSubclassed = false;
}
}
class B extends A {
public B() {
super();
}
@Override
public void f() {}
}
public class Init {
public static void main(String[] args) {
new B(); //Subclass.
new A();
}
}
该程序的输出是:
I'm subclassed.
I'm not subclassed.
Here A
知道它已被子类化。不知道是谁干的,但这并不重要。这是如何解释的呢?我是不是被误导了?
The NullPointerException
发生这种情况是因为当您构造 B 的实例时,会调用父构造函数(在 A 中)。这个构造函数调用f()
方法,但由于对象的实际类型是 B,因此被重写f()
调用B中的方法。
@Override
public void f() {
//Anything that access o.
o.hashCode(); //Throws NullPointerException as o has not been initialised yet
super.f();
}
这里的教训是永远不要在构造函数中调用可以被子类覆盖的方法。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)