我有以下Java代码
public class Base {
private static boolean goo = true;
protected static boolean foo() {
goo = !goo;
return goo;
}
public String bar = "Base:" + foo();
public static void main(String[] args) {
Base base = new Sub();
System.out.println(base.bar);
}
}
public class Sub extends Base {
public String bar = "Sub:" + foo();
}
我被问到会打印什么。经过测试后,答案似乎是Base:false
,但我真的无法理解为什么它不是Sub:true
。
显示具有两个具有相同名称的变量的基数!一个有印刷的基础:假,另一个是预期的(由我)Sub:true。实际上foo()被调用两次但每次实例化一个不同的变量?不应该在子类中创建具有相同名称的变量(并在创建第一个之后初始化)覆盖父类中的变量吗? Java如何选择要打印哪一个?
答案 0 :(得分:6)
...显示具有两个具有相同名称的变量的基础!
烨! base
是对Sub
个实例的引用,Sub
个实例有两个 bar
个字段。我们称他们为Base$bar
和Sub$bar
:
+------------------------+ base--->| Sub instance | +------------------------+ | Base$bar: "Base:false" | | Sub$bar: "Sub:true" | +------------------------+
Java允许在实例的类型层次结构中的不同级别使用相同的名称。 (它必须:经常这些是私有字段,因此子类甚至可能不知道超类具有相同名称的字段。)
实例中的这两个不同字段具有不同的值:Base$bar
具有值Base:false
,因为它是根据对foo
的第一次调用进行初始化的, goo
(以true
开头)并使用翻转结果。 Sub$bar
的值为Sub:true
,因为它是从第二次调用foo
初始化的,因此再次翻转goo
并使用更新后的值。只创建了一个实例,但foo
被调用了两次。
访问bar
时看到的bar
取决于您对实例的引用类型。由于base
被声明为Base
类型,因此当您执行base.bar
时,您将访问Base$bar
实例中的Sub
字段。如果您对该实例有Sub
引用,则可以访问Sub$bar
:
System.out.println(base.bar); // "Base:false"
System.out.println(((Sub)base).bar); // "Sub:true"