下式给出:
class A
{
String s = "A";
}
class B extends A
{
String s = "B";
}
public class C
{
public static void main(String[] args){ new C().go();}
void go()
{
A a = new B();
System.out.println(a.s);
}
}
问题:
运行此代码时JVM背后的机制是什么?为什么a.s打印回“A”。
答案 0 :(得分:4)
字段引用不受多态性的影响,因此在编译时编译器引用A的字段,因为您的局部变量是A类型。
换句话说,字段行为就像方法上的Java重载行为,而不是Java重写行为。
答案 1 :(得分:2)
您可能希望像方法一样覆盖字段,并根据对象的运行时类型进行动态分派。
这不是Java的工作方式。字段不会被覆盖,它们是隐藏的。这意味着B类的对象有两个字段,名为“s”,但访问哪些字段取决于上下文。
至于为什么会这样:覆盖字段是没有意义的,因为当类型不同时没有任何有用的方法可以使它工作,而当类型相同时就没有意义了(就像你一样)可以只使用超类字段)。就个人而言,我认为它应该只是一个编译器错误。
答案 2 :(得分:1)
这不是多态(如标记)。
Java有virtual methods,而不是虚拟成员变量 - 即你没有覆盖属性 - 你隐藏它。
答案 3 :(得分:0)
虽然成员变量是从基类继承的,但它们不是多态调用的(即动态调用不适用于成员变量)。
因此,a.s将引用基类中的成员而不是派生类。
话虽如此,代码并未遵循OO原则。类的成员需要是私有/受保护的(不是公共的或默认的),具体取决于业务用例,您需要提供公共方法来获取和设置成员的值。