嗨,我有以下简单的课程。
class A {
int i;
int y;
A(int i, int y)
{
}
然后当我尝试在下面进行操作
class B extends A
{
B()
{
super(i, y);
}
}
我得到错误提示 “在显式调用构造函数时无法引用实例字段y”。 我知道这是错误的,但是我想知道为什么我不能这样做。由于A的构造函数首先被初始化,因此i和y的值均为0,为什么不能将这些值传递给超级构造函数。
答案 0 :(得分:4)
由于A的构造函数首先被初始化,所以i和y的值均为0,为什么不能将这些值传递给超级构造函数。
问题是super(i, y)
(在B
中)的参数表达式在调用A
构造函数之前被求值。
new B()
的执行顺序如下:
B
及其依赖项的静态初始化被触发(如果尚未发生)。B
的构造函数参数的参数表达式进行求值。 (在这种情况下,没有任何东西。)
B
的类型对其进行初始化,并且所有字段(在B
及其超类中)都是默认初始化的。super
的{{1}}参数。B
的{{1}}参数。super
构造函数主体。A
和Object()
字段将被初始化(如果它们具有初始化程序)。A.i
构造函数主体。 A.y
的字段初始化程序将被执行。A(int,int)
构造函数主体。B
实例的引用。 如您所见,步骤4将引用B()
,该变量将在步骤7中被 1 初始化。
注意:以上内容已简化。有关完整的规范,请参见JLS 15.9.4。
1-规则未考虑您的示例中没有初始化程序的事实。但这是一件好事。 1)考虑到这一点会使它们变得更加复杂和令人惊讶。 2)如果您知道具有默认值,则允许访问变量的实用工具是什么?您可以使用该值!