为什么在显式调用构造函数java时无法引用实例字段

Sha*_*lva 2 java constructor

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

class A {
int i;
int y;

A(int i, int y)
{

}
Run Code Online (Sandbox Code Playgroud)

然后当我尝试以下

class B extends A
{
    B()
    {
        super(i, y);        
    }
}
Run Code Online (Sandbox Code Playgroud)

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

Ste*_*n C 5

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

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

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

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

如您所见,步骤4指的是y尚未初始化的1。在第7步之前不会对其进行初始化。

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


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