【问题标题】:When is a Java Implicit Constructor called compared to the Base Class Constructor?与基类构造函数相比,何时调用 Java 隐式构造函数?
【发布时间】:2015-02-25 02:14:55
【问题描述】:

如果我有这样的事情:

public class SuperClass
{
    SuperClass()
    {
        x = true;
    }
    public boolean x;
}

public class SubClass extends SuperClass
{
    SubClass()
    {
        x = false;
    }
}

我最终制作了一个SubClass 对象。 x 是真还是假?来自http://docs.oracle.com/javase/specs/jls/se5.0/html/execution.html#12.5 看起来会是假的。

【问题讨论】:

  • 在您的示例中,基类和超类之间没有联系。
  • SuperClassBaseClass 在您的示例中是独立的。
  • 你的类名很混乱,BaseClass不应该扩展SuperClass吗?同样在这种情况下,它的名字不应该更像SubClassDerivedClass吗?

标签: java class inheritance constructor


【解决方案1】:

来自Section 12.5 of the Java Language Specification(相关部分以粗体表示):

就在对新创建对象的引用作为结果返回之前,使用以下过程处理指示的构造函数以初始化新对象:

  1. 将构造函数的参数分配给此构造函数调用的新创建的参数变量。

  2. 如果此构造函数以同一类中另一个构造函数的显式构造函数调用(第 8.8.7.1 节)开始(使用 this),则评估参数并使用这五个相同的步骤递归地处理该构造函数调用。如果该构造函数调用突然完成,则此过程出于相同原因而突然完成;否则,继续第 5 步。

  3. 此构造函数不是以显式构造函数调用同一类中的另一个构造函数开始的(使用 this)。如果此构造函数用于 Object 以外的类,则此构造函数将以显式或隐式调用超类构造函数开始(使用 super)。 使用这五个相同的步骤以递归方式评估超类构造函数调用的参数和过程。 如果该构造函数调用突然完成,则此过程出于相同的原因突然完成。否则,继续执行第 4 步。

  4. 执行该类的实例初始化程序和实例变量初始化程序,将实例变量初始化程序的值分配给相应的实例变量,按照它们在源代码中以文本形式出现的从左到右的顺序。如果执行这些初始化程序中的任何一个导致异常,则不会处理更多初始化程序,并且此过程会突然完成相同的异常。否则,继续第 5 步。

  5. 执行此构造函数的其余部分。如果该执行突然完成,则此过程出于相同的原因突然完成。否则,此过程正常完成。

因此将首先调用父类的构造函数(步骤 3),将 x 设置为 true。在超类的构造函数使用相同的步骤递归处理并完成后,子类的构造函数的主体将其设置为false(步骤5)。

【讨论】:

    【解决方案2】:

    在代码的原始版本 [*] 中,这两个类是不相关的,BaseClass 甚至无法编译,因为没有声明或继承 x

    如果您将BaseClass 设为SuperClass 的子类,则x 将是false,因为SuperClass 的构造函数将在BaseClass 之前运行。

    [*] 在有人编辑问题添加extend SuperClass之前。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-07-19
      • 2018-07-21
      • 2017-12-08
      • 2015-02-09
      • 2018-02-28
      • 2015-08-18
      • 2018-07-16
      相关资源
      最近更新 更多