在 Java 中隐藏名称的误导性示例
Misleading example of hiding names in Java
请查看以下来源:
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
?它应该从 class Base
中检索 className
,因为在 Derived
class 中它是 private
。
然而,setter setClassName
设置 public className
在 class 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
谁能解释一下这个奇怪的事情?
简答:字段不能覆盖同名字段,只能使其不可见。这是方法的主要区别。
为什么打印 "b" 和 "d"
您有两个字段,一个在 Base
中,一个在 Derived
中,它们(风格不佳)恰好具有相同的名称 className
。但它们是完全不同的东西。如果将 Base class 重命名为 baseClassName,将 Derived 重命名为 derivedClassName,代码的行为将相同。 (从现在开始,我将使用新名称来说明发生了什么。)
您在 Base
中有一个 setClassName()
方法,它将 Base
class 中已知的名为 className
的字段设置为 baseClassName
字段。该方法甚至不知道在某些子 class 中可能有另一个字段碰巧有一个冲突的名称。由于 Java 中没有字段覆盖,它设置 baseClassName
,而不是 derivedClassName
.
test()
方法引用 Base.className
,是 baseClassName
字段,从不引用 derivedClassName
。所以此方法打印在 setClassName() 调用中设置的值。
请查看以下来源:
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
?它应该从 class Base
中检索 className
,因为在 Derived
class 中它是 private
。
然而,setter setClassName
设置 public className
在 class 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
谁能解释一下这个奇怪的事情?
简答:字段不能覆盖同名字段,只能使其不可见。这是方法的主要区别。
为什么打印 "b" 和 "d"
您有两个字段,一个在 Base
中,一个在 Derived
中,它们(风格不佳)恰好具有相同的名称 className
。但它们是完全不同的东西。如果将 Base class 重命名为 baseClassName,将 Derived 重命名为 derivedClassName,代码的行为将相同。 (从现在开始,我将使用新名称来说明发生了什么。)
您在 Base
中有一个 setClassName()
方法,它将 Base
class 中已知的名为 className
的字段设置为 baseClassName
字段。该方法甚至不知道在某些子 class 中可能有另一个字段碰巧有一个冲突的名称。由于 Java 中没有字段覆盖,它设置 baseClassName
,而不是 derivedClassName
.
test()
方法引用 Base.className
,是 baseClassName
字段,从不引用 derivedClassName
。所以此方法打印在 setClassName() 调用中设置的值。