我有以下情况:
public abstract class A {
private Object superMember;
public A() {
superMember = initializeSuperMember();
// some additional checks and stuff based on the initialization of superMember (***)
}
protected abstract Object initializeSuperMember();
}
class B extends A {
private Object subMember;
public B(Object subMember) {
super();
subMember = subMember;
}
protected Object initializeSuperMember() {
// doesn't matter what method is called on subMember, just that there is an access on it
return subMember.get(); // => NPE
}
}
问题是我在创建新对象B时获得了NPE
我知道我可以通过在子类构造函数中分配subMember内容后调用initializeSuperMember()来避免这种情况,但这意味着我必须为每个子类执行此操作(在代码中标记为 * ) 。
因为我必须在子类构造函数中调用super()作为第一件事,所以在调用super()之前我无法初始化subMember。
任何人都想告诉我,如果有更好的方法可以做到这一点,或者我是否想要做一些完全错误的事情?
答案 0 :(得分:2)
两个问题:
首先,您应该永远不要从构造函数中调用可重写的成员函数,因为您发现的原因。有关该问题的详细讨论,请参阅this thread。
其次,在B的构造函数中,您需要:
this.subMember = subMember;
构造函数参数名称掩盖了字段名称,因此您需要this.
来引用该字段。
答案 1 :(得分:0)
遵循调用链:
B()
构造函数。A()
构造函数。A()
构造函数调用重写的抽象methot B#initializeSuperMember()
引用尚未初始化的subMember
。 NPE。做你做的事永远无效。
此外,目前还不清楚你想要完成什么。你应该问一个单独的问题来解释你的目标是什么。
答案 2 :(得分:0)
问题是当你调用super()时,subMember尚未初始化。您需要将subMemeber作为参数传递。
public abstract class A {
public A (Object subMember) {
// initialize here
}
}
class B extends A {
public B (Object subMember) {
super(subMember);
// do your other things
}
}
由于您不希望在抽象类中使用subMember,因此另一种方法是覆盖getter。
public abstract class A {
public abstract Object getSuperMember();
protected void checkSuperMember() {
// check if the supberMember is fine
}
}
public class B extends A {
private Object subMember;
public B(Object subMember) {
super();
this.subMember = subMember;
checkSuperMemeber();
}
@Override
public Object getSuperMember() {
return subMember.get();
}
}
我希望这也可以删除您的重复代码。
答案 3 :(得分:0)
public static abstract class A {
public abstract Object createObject();
}
public static abstract class B extends A {
private Object member;
public B(Object member) {
super();
this.member = member;
}
}
public static B createB(final Object member) {
return new B(member) {
@Override
public Object createObject() {
return member.getClass();
}
};
}