请看下面的代码:
class Rodent {
protected int tailLength = 4;
public void getRodentDetails() {
System.out.println(this.tailLength);
}
}
public class Mouse extends Rodent {
protected int tailLength = 8;
public static void main(String[] args) {
Mouse mouse = new Mouse();
mouse.getRodentDetails();
}
}
现在继承getRodentDetails()
。
当Mouse
引用调用时,this.tailLength
应该打印8
而不是4
,因为父级tailLength
隐藏在鼠标中。
为什么打印4?
编辑:问题不在于什么是变量隐藏,也不在于如何尝试覆盖变量。最接近的答案是JB Nizet在评论中给出的,我将其作为答案进行了扩展。
答案 0 :(得分:2)
在Java中,您可以使用overwrite方法,而不是属性。但你可以隐藏它们。
因此,无论何时在tailLength
类内部调用Mouse
属性,您都会隐藏tailLength
类的Rodent
属性,并使用Mouse
中的值类。
如果要覆盖此值,则应使用此结构:
class Rodent {
// we add final to make sure value is always set
protected final int tailLength;
// default constructor
protected Rodent() { this(4); }
// use to overwrite tailLength value
protected Rodent(int tailLength ) { this.tailLength =tailLength; }
public void getRodentDetails() {
System.out.println(this.tailLength);
}
}
鼠标类:
public class Mouse extends Rodent {
public Mouse (){
super(8);
}
...
}
这样你就可以设置尾巴长度而不会有任何覆盖,只需使用OOP。
答案 1 :(得分:1)
嗯,这是因为static binding。
1)Java中的静态绑定发生在Dynamic的编译时 绑定发生在运行时。
2)私有方法,最终方法和静态方法和变量使用静态绑定,并在虚拟方法时由编译器绑定 在运行时根据运行时对象进行绑定。
3)静态绑定使用Type(Java中的Class)信息进行绑定 而动态绑定使用Object来解析绑定。
4)在重写时使用静态绑定绑定重载方法 方法在运行时使用动态绑定进行绑定。
所以,
protected int tailLength = 4;
public void getRodentDetails() {
System.out.println(this.tailLength);
}
在此代码中,tailLength仅在编译时与Rodent类的tailLength变量相关联。
为什么this
没有影响它?
这是因为this
在运行时被解析为内存地址。
有些人说这是由于变量隐藏,但由于静态绑定而发生变量隐藏。
答案 2 :(得分:0)
变量不会被覆盖,就像你应该在构造函数
中初始化它们一样 public Mouse (){
super.tailLength = 8;
}
通过定义它将生成鼠标类未知的其他变量
答案 3 :(得分:0)
简而言之,来自Oracle Documentation(我的重点):
在一个类中,一个字段与相同的名称作为字段中的字段 超类隐藏超类的字段,即使它们的类型是 不同。
由此我们了解到成员字段不能像方法一样被覆盖。
超级tailLength
中的Rodent
字段已隐藏,无法以多态方式进行访问。
在超类tailLength
中访问Rodent
的一种方法是通过强制转换,例如:
System.out.println(((Rodent)mouse).tailLength);