作者:勇往直前 | 来源:互联网 | 2022-12-02 17:28
嗨,我有以下简单的课程。
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> Stephen C..:
由于A的构造函数首先被初始化,因此i和y的值均为0,为什么不能将这些值传递给超级构造函数。
问题在于super(i, y)
(in中B
)中参数的表达式是在调用A
构造函数之前求值的。
的执行顺序new B()
如下:
B
触发了及其及其依赖项的静态初始化(如果尚未发生)。
B
评估的构造函数参数的参数表达式。(在这种情况下,没有任何东西。)
创建一个堆节点B
,并使用的类型对其进行初始化,并且所有字段(in B
及其超类)都默认进行了初始化。
在super
对参数B
进行评估。
在super
对参数A
进行评估。
该Object()
构造函数体被执行。
字段A.i
和A.y
将被初始化(如果它们具有初始化程序)。
该A(int,int)
构造函数体被执行。
B
的字段初始化程序将被执行。
该B()
构造函数体被执行。
B
返回对已完成实例的引用。
如您所见,步骤4指的是y
尚未初始化的1。在第7步之前不会对其进行初始化。
注意:以上内容已简化。有关完整规范,请参阅JLS 15.9.4。
1-规则未考虑示例中没有初始化程序的事实。但这是一件好事。1)考虑到这一点会使它们变得更加复杂和令人惊讶。2)如果您知道变量具有默认值,则允许它访问变量的用途是什么?您可以直接使用该值!