请原谅任何轻微的语法错误或其他什么,我正在使用Jitsi模块遇到这种情况,并且不熟悉Java,想要确认发生了什么以及为什么以及如何修复它。
public abstract class A
{
public A()
{
this.load();
}
protected void load()
{
}
}
public class B extends A
{
private String testString = null;
public B()
{
super();
}
@Override
protected void load()
{
testString = "test";
}
}
应用程序在使用按名称加载类方法创建类B的实例时执行此操作:
这是预期的Java行为吗?什么可能导致这个?它是在1.7 JDK上运行的Java 1.6应用程序。
答案 0 :(得分:59)
这是预期的Java行为吗?
是
是什么导致这个?
您在非final超类构造函数中调用非最终重写方法。
让我们一步一步看看会发生什么:
B
。B()
调用超类构造函数 - A()
来初始化超类成员。A()
现在调用一个非final方法,该方法在B
类中被覆盖,作为初始化的一部分。B
类,因此调用的方法load()
为B
类。load()
初始化B
类实例字段 - testString
。Object
类已完成)B()
构造函数开始执行,初始化它自己的成员。B
会覆盖testString
中之前的书面值,并将其重新初始化为null
。道德:永远不要在它的构造函数中调用非final类的非final方法。
答案 1 :(得分:5)
这是一个常见的问题模式,具有构建初始化,并且经常可以在基础设施代码中找到。自制的DAO。
“null”的分配是不必要的&可以删除。
如果这还不够快,那么:将所有构造后的init移动到一个单独的方法,并将其全部包装在“静态方法”伪构造函数中。
如果你正在做DAO的东西,区分“加载”和“创建”真的很好,因为这些是完全不同的实例。定义单独的“静态构造函数”方法&也许是单独的内部因素。
abstract public class A {
protected void initAfterCreate() {}
}
public class B {
@Override
protected void initAfterCreate() {
this.testString = "test";
}
// static constructors;
// --
static public B createB() {
B result = new B();
result.initAfterCreate();
}
}
演示DAO的加载/创建分隔:
public class Order {
protected int id;
protected boolean dbExists;
static public load (int id) {
Order result = new Order( id, true);
// populate from SQL query..
return result;
}
static public create() {
// allocate a key.
int id = KeyAlloc.allocate( "Order");
Order result = new Order( id, false);
}
// internal constructor; not for external access.
//
protected Order (int id, boolean dbExists) {
this.id = id;
this.dbExists = dbExists;
}
}