参加这个基类:
public abstract class XMPPSubservice
{
protected XMPPService mTheService;
protected XMPPSubservice(Context context)
{
Intent intent = new Intent(context, XMPPService.class);
context.startService(intent);
}
public void onServiceInstance(XMPPService service) {
// TODO Auto-generated method stub
mTheService = service;
}
}
这个派生类:
public class PublicDataSubservice extends XMPPSubservice
{
private final SomeObject mObj = new SomeObject();
public PublicDataSubservice(Context context) {
super(context);
}
@Override
public void onServiceInstance(XMPPService service)
{
super.onServiceInstance(service);
mObj.doSomethingWith(mTheService);
}
}
目标是只调用mObj.doSomethingWith(mTheService); mTheService生效后(发生在基类中)。事情是它总是在mObj线上吐出NPE。我能理解为什么会这样,但它对我来说看起来很不可思议。那么这是DVM的一个bug还是一个功能? JVM怎么样?
答案 0 :(得分:5)
这完全正确,也会出现在“vanilla”Java中。
实例变量初始值设定项仅在超类构造函数完成执行后在构造函数体的开头执行。因此,当XMPPSubservice
构造函数正在执行时,mObj
为空 - 然后从构造函数中调用虚方法,并执行PublicDataService
中的覆盖。
道德:不要从构造函数中调用虚方法,除非你真的必须这样做,在这种情况下你应该非常仔细地记录它们。 (偶尔它很有用,但你应该尽力避免它。)基本上它意味着你最终会调用一个可能部分初始化的对象,这就是这里发生的事情。
答案 1 :(得分:1)
我在Java VM中使用对象的存根实现尝试了以下操作。
public static void main(String[] args) {
Context context = new Context();
PublicDataSubservice pds = new PublicDataSubservice(context);
XMPPService service = new XMPPService();
pds.onServiceInstance(service);
}
否NullPointerException
。
我错过了什么吗?我想onServiceInstance
实际上必须调用context.getService(intent)
?