从构造函数调用方法
请原谅任何小的语法错误或什么,我正在经历这与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"; } }
应用程序在使用加载类名称方法创build类B的实例时执行此操作:
- 在类B中调用重载的load()
- 初始化variables(根据debugging器调用“private string testString = null”),将它们归零。
这是预期的Java行为? 什么可能导致这个? 这是在1.7 JDK上运行的Java 1.6应用程序。
这是预期的Java行为?
是。
什么可能导致这个?
您在非最终超类构造函数中调用非最终重写的方法。
让我们看看发生了什么事情:
- 您创build一个
B
的实例。 -
B()
调用超类的构造函数A()
来初始化超类的成员。 -
A()
现在调用一个在B
类中被重载的非final方法,作为初始化的一部分。 - 由于上下文中的实例是
B
类的,调用的方法load()
是B
类的。 -
load()
初始化B
类实例字段 –testString
。 - 超类构造函数完成作业,并返回(假设构造函数的链接直到
Object
类已完成) -
B()
构造函数开始执行进一步,初始化它自己的成员。 - 现在,作为启动过程的一部分,
B
覆盖testString
的前一个写入值,并将其重新初始化为null
。
道德:永远不要在构造函数中调用非final类的非公开方法。
这是一个常见的问题模式,在构build初始化时,可以经常在基础架构代码和自制的DAO中find。
对'null'的赋值是不需要的,可以被删除。
如果这还不够快,那么:将所有构build后的init移动到一个单独的方法中,并将其全部包装到“静态方法”伪构造器中。
如果你正在做DAO的东西,区分“加载”和“创build”真的很好,因为这些是完全不同的实例。 定义单独的“静态构造函数”方法,也许单独的内部inits,这些。
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的加载/创build分离:
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; } }