为什么在显式调用构造函数java

时间:2018-10-09 15:22:21

标签: java constructor

嗨,我有以下简单的课程。

class A {
int i;
int y;

A(int i, int y)
{

}

然后当我尝试在下面进行操作

class B extends A
{
    B()
    {
        super(i, y);        
    }
}

我得到错误提示 “在显式调用构造函数时无法引用实例字段y”。 我知道这是错误的,但是我想知道为什么我不能这样做。由于A的构造函数首先被初始化,因此i和y的值均为0,为什么不能将这些值传递给超级构造函数。

1 个答案:

答案 0 :(得分:4)

  

由于A的构造函数首先被初始化,所以i和y的值均为0,为什么不能将这些值传递给超级构造函数。

问题是super(i, y)(在B中)的参数表达式在调用A构造函数之前被求值。

new B()的执行顺序如下:

  1. B及其依赖项的静态初始化被触发(如果尚未发生)。
  2. B的构造函数参数的参数表达式进行求值。 (在这种情况下,没有任何东西。)
  3. 创建堆节点,并使用B的类型对其进行初始化,并且所有字段(在B及其超类中)都是默认初始化的。
  4. 评估super的{​​{1}}参数。
  5. 评估B的{​​{1}}参数。
  6. 执行super构造函数主体。
  7. AObject()字段将被初始化(如果它们具有初始化程序)。
  8. 执行A.i构造函数主体。
  9. A.y的字段初始化程序将被执行。
  10. 执行A(int,int)构造函数主体。
  11. 返回对完成的B实例的引用。

如您所见,步骤4将引用B(),该变量将在步骤7中被 1 初始化。

注意:以上内容已简化。有关完整的规范,请参见JLS 15.9.4


1-规则未考虑您的示例中没有初始化程序的事实。但这是一件好事。 1)考虑到这一点会使它们变得更加复杂和令人惊讶。 2)如果您知道具有默认值,则允许访问变量的实用工具是什么?您可以使用该值!