我有以下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();
}
Run Code Online (Sandbox Code Playgroud)
而且我被问到它会打印什么.经过测试,答案似乎是Base:false,但我真的无法理解为什么不是Sub:true.
它显示了具有两个同名变量的基数!一个有印刷的基础:假,另一个是预期的(由我)Sub:true.实际上foo()被调用两次但每次实例化一个不同的变量?不应该在子类中创建具有相同名称的变量(并在创建第一个之后初始化)覆盖父类中的变量吗?Java如何选择打印哪一个?
...显示具有两个同名变量的基数!
对!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"
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
73 次 |
| 最近记录: |