gpt4 book ai didi

Java 不明确的结果

转载 作者:塔克拉玛干 更新时间:2023-11-01 22:54:21 25 4
gpt4 key购买 nike

我定义了三个类(A、B、C):

public class A {
int i = 5;
public A() {
foo();
}
public void foo() {
System.out.println(i);
}
}

class B extends A {
int i = 6;
}

class C extends B {
int i = 7;
public void foo() {
System.out.print(super.i);
}
public static void main(String[] args) {
C c = new C();
}
}

预期结果是:6但程序返回:0

谁能解释一下结果?您的帮助将不胜感激。

最佳答案

Class C 覆盖了 A.foo(),并且多态性甚至在 Java 的构造函数中也是活跃的。因此,当我们构建 C 的实例时,A 中的构造函数调用 foo() 时,它是 C.foo() 实际被调用。

C.foo() 依次打印出 B.i,因此我们可能期望 6 被打印出来out - 但实例变量初始值设定项仅在父类(super class)构造函数之后执行,因此在执行时,B.i 为 0。

基本上,构造函数的执行顺序是:

  • 执行链接构造函数,显式 this(...) 链接到同一类中的另一个构造函数,或显式 super(...) 链接到父类(super class)中的构造函数,或隐式 super() 链接到父类(super class)中的无参数构造函数。
  • 对于链接到父类(super class)构造函数的构造函数,执行变量初始值设定项。
  • 执行构造函数体中的代码

重写代码以避免使用变量初始值设定项和变量阴影使这一点更加清晰,同时仍然保持代码等效:

public class A {
int ai;

public A() {
super();
ai = 5;
foo();
}

public void foo() {
System.out.println(ai);
}
}

class B extends A {
int bi;

public B() {
super();
bi = 6;
}
}

class C extends B {
int ci;

public C() {
super();
ci = 7;
}

public void foo() {
System.out.print(bi);
}

public static void main(String[] args) {
C c = new C();
}
}

顺便说一句,如果您一开始就将所有字段设为私有(private),那么“变量隐藏”部分就不会发挥作用,这是我的建议。这只是留下了从构造函数调用虚拟方法的问题,这通常是一个坏主意,因为期望对象在它有机会完全初始化之前能够工作,并且变量初始化程序执行的时间可能令人惊讶。

如果您避免从构造函数中调用虚方法,甚至变量初始化器的时间也变得无关紧要 - 至少几乎始终如此。

关于Java 不明确的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7376847/

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