gpt4 book ai didi

java - 哪个先跑?实例变量或 super 构造函数的默认值?

转载 作者:搜寻专家 更新时间:2023-11-01 02:25:04 24 4
gpt4 key购买 nike

根据 SCJP6(第 507 页),我发现实例变量在父类(super class)构造函数完成之前被分配了默认值,我在 Debugg 模式下尝试了一个示例,但我看到 super 承包商在实例变量获得默认值之前运行,可以有人给我解释一下吗?

我使用的示例以防有人想尝试:

package courseExercise;

class test {
test() {
System.out.println("Super Constructor run");
}
}

public class Init extends test {

private Integer i = 6;
private int j = 8;

Init(int x) {
super();
System.out.println("1-arg const");
}

Init() {
System.out.println("no-arg const");
}

static {
System.out.println("1st static init");
}
public static int d = 10;
{
System.out.println("1st instance init");
}
{
System.out.println("2nd instance init");
}
static {
System.out.println("2nd static init");
}

public static void main(String[] args) {
new Init();
new Init(7);
}
}

最佳答案

初始化顺序在JLS 12.5中指定:

  1. 首先,为新对象分配内存
  2. 然后对象中的所有实例变量(包括在该类及其所有父类(super class)中定义的实例变量)都被初始化为其默认值
  3. 最后调用构造器。

规范的相关部分是:

...

If there is not sufficient space available to allocate memory for the object, then creation of the class instance completes abruptly with an OutOfMemoryError. Otherwise, all the instance variables in the new object, including those declared in superclasses, are initialized to their default values (§4.12.5).

Just before a reference to the newly created object is returned as the result, the indicated constructor is processed to initialize the new object using the following procedure:

...

这是您永远不应从构造函数调用非final 方法的原因之一:该方法可能会被子类覆盖,在这种情况下,该方法将在子类之前被调用有机会设置方法可能需要的状态。考虑这个例子:

public class Super {
private final int superValue;

protected Super() {
superValue = getSuperValue();
}

protected int getSuperValue() {
return 1;
}

@Override
public String toString() {
return Integer.toString(superValue);
}
}

public class Sub extends Super {
private final int superValueOverride;

public Sub(int value) {
this.superValueOverride = value;
}

@Override
protected int getSuperValue() {
return superValueOverride;
}

public static void main(String[] args) {
Super s = new Sub(2);
System.out.println(s);
}
}

看起来s.superValue应该是2吧?毕竟,Sub 覆盖了 getSuperValue() 以返回 superValueOverride 的值,它被初始化为 2。但是该方法在任何Sub 的字段被初始化(除了它们的默认值),所以 s.superValue 实际上是 0(superValueOverride 的默认值) .

这更奇怪,因为 superValueOverridefinal,但它似乎改变了它的值!当 Super 调用 getSuperValue() 时它是 0,并且只有在 Super 构造函数完成后它才被赋予它的最终值 2(或者传递的任何值)进入构造函数)。

关于java - 哪个先跑?实例变量或 super 构造函数的默认值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26552799/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com