从构造函数调用方法

请原谅任何小的语法错误或什么,我正在经历这与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; } }