请查看以下来源:
public class Base {
public String className = "Base";
public void setClassName(String className){
this.className = className;
}
}
public class Derived extends Base {
private String className = "Derived";
}
public class PrivateMatter {
private static void test (Base b){
System.out.println(b.className);
}
public static void main (String[] args){
Derived d = new Derived();
d.setClassName("d");
Base b = new Base();
b.setClassName("b");
test(b); // it prints b
test(d); // it prints d
}
}
我期待输出:
b
Base
应该做什么test
?它应该从类className
中检索Base
,因为在Derived
类中它是private
。
但是,如果是setClassName
,则设置者className
设置公开Base
,className
设置私有字段Derived
。这是我的直觉。
为了总结(我的思维方式):
Derived d = new Derived();
d.setClassName("d"); // it set private field (which did hide field from class Base)
Base b = new Base();
b.setClassName("b"); // it set public field (which is originally placed in `Base` class
test(b); // it prints b - it is ok for me
test(d); // it prints d - why ? After all, d.setClassName("d") should modify private field, however test should print public field
有人可以解释这个奇怪的事吗?
答案 0 :(得分:1)
简短回答:字段无法覆盖同名字段,只能使其不可见。这是方法的一个主要区别。
您有两个字段,一个在Base
,另一个在Derived
,其中(按错误样式)碰巧具有相同的名称className
。但它们完全不同。如果将Base类1重命名为baseClassName,将Derived one重命名为derivedClassName,则代码的行为将相同。 (从现在开始,我将使用新名称来说明会发生什么。)
setClassName()
中有一个Base
方法,它设置了className
类中已知的Base
字段,即baseClassName
字段。这种方法甚至不知道在某些子类中可能会有另一个字段发生碰撞名称。由于Java中没有字段覆盖,因此设置baseClassName
,而不是derivedClassName
。
test()
方法引用Base.className
,即baseClassName
字段,而不是derivedClassName
。因此,此方法打印在setClassName()调用中设置的值。