我注意到一些奇怪的行为。我有以下课程:
public abstract class BaseFoo
{
public BaseFoo(String key)
{
Data data = Something.load( key );
load( data );
}
public abstract void load(Data data);
}
public class Foo extends BaseFoo
{
@Expose public long id = 0;
@Expose public String name = "";
//...
public Foo(String key)
{
super(key);
}
@Override
public void load(Data data)
{
this.id = data.id;
this.name = data.name;
//snip setting misc other fields
}
}
现在,如果我执行以下操作:
Foo f = new Foo ( "abcd" );
然后我希望f.id
包含已加载的Foo
记录的ID。但是,其值实际为0
。通过调试器运行此代码,我发现在Foo.load()
行执行之前调用了public long id = 0
。因此,虽然load()
被调用并且它确实将id
和其他字段设置为正确的值,但这些值会被public long id = 0;
和其他变量声明覆盖..
我之前从未遇到过这个问题,通常在构造函数中设置的值会覆盖变量声明中的默认值。是因为我通过super
调用加载值是否被覆盖?如果是这样,是否有方便的解决方法呢?
答案 0 :(得分:7)
这是在构造函数中调用虚方法的问题......
执行顺序是:
JLS, section 12.5中记录了这种行为。
所以实际上是,如果你改变了这些:
@Expose public long id = 0;
@Expose public long name = "";
到
@Expose public long id;
@Expose public String name;
然后有条件地将name
设置为“”,如果它到达Foo
构造函数体时尚未为空,那么我认为你会没关系。
但是,我强烈建议您使用不同的设计来解决这个问题。构造函数中的虚方法调用非常快速地变得非常混乱。