我刚开始学习Java,所以如果答案有点明显,请耐心等待。我做了一些研究但没有用。
根据我的理解,属性不会被覆盖,只会隐藏字段。为了确定是否使用了超类或子类中的属性,Java将检查引用的类型。
然后我不知道这里的输出:
public class Super {
String str = "I'm super!\n";
public String toString() {
return str;
}
}
public class Sub extends Super {
String str = "I'm sub.\n";
}
public class TestFH {
public static void main(String[] args) {
Sub s1 = new Sub();
System.out.printf(s1.toString());
}
}
它给了我:
I'm super!
我知道我可以通过方法覆盖轻松实现我想要的目标。我只是对引擎盖下发生的事情感到好奇。
提前致谢。
答案 0 :(得分:3)
当你致电s1.toString()
时,它发现只在toString()
类中定义Super
方法,因此使用该方法,因为子类中有超类方法。 您的超类方法toString()
正在使用它自己的类变量str
(在超类中初始化值)作为方法的返回值,因此行为即输出为{ {1}}。
如果要将输出作为I'm super!
,则需要重用与超类中相同的变量,并为其分配新的字符串值,即I'm sub.\n
。最好的选择是使用构造函数:
I'm sub.\n
答案 1 :(得分:2)
你在你的孩子班级中隐藏(遮蔽)str
。由于您未在子类中重写toString()
,因此将在父类中进行调用,并且它将看到父类str
。
如果你这样做了:
public class Sub extends Super {
public Sub() {
this.str = "I'm sub.\n";
}
}
它会输出你期望的东西。
答案 2 :(得分:1)
此调用使用超类:
Sub s1 = new Sub();
System.out.printf(s1.toString());
原因是 Sub没有覆盖 str
,它只是声明另一个恰好具有相同名称的变量。换句话说,sub只是将变量隐藏在Super
中(数据成员不是多态的)。
如果它们意味着不同的东西,你可以给它们不同的名字。或者可以使用getter方法Sub
访问(或修改)父项的属性。
答案 3 :(得分:1)
您没有将字符串文字"I'm sub.\n"
分配给共享超类字段,而是创建子类本地的字段并将其分配给该字段。
例如,
public class EncapsulationDemo {
public static void main(String[] args){
MySuperObject obj = new MySubObject();
System.out.println(obj); // prints I'm sub.
}
private static class MySuperObject{
String str = "I'm super."; // protected, can be accessed directly
// by subclasses
@Override
public String toString(){
return str;
}
}
private static class MySubObject extends MySuperObject{
MySubObject(){
super();
str = "I'm sub."; // assign to superclass field
}
}
}
有关详细信息,请参阅Controlling Access to Members of a Class。