Java 继承和类成员

Java 继承和类成员,java,polymorphism,Java,Polymorphism,鉴于: 问题: 运行此代码时,JVM背后的机制是什么?为什么a.s打印的是“a” 字段引用不受多态性的约束,因此在编译时编译器正在引用A的字段,因为您的局部变量是A类型的 换句话说,字段行为类似于方法上的Java重载行为,而不是Java重写行为。这不是多态性(标记) Java没有虚拟成员变量(即不重写属性),而是将其隐藏。您可能希望字段像方法一样被重写,并根据对象的运行时类型进行动态分派 Java不是这样工作的。字段不会被覆盖,而是被隐藏。这意味着类B的对象有两个名为“s”的字段,但访问哪一个字

鉴于:

问题:


运行此代码时,JVM背后的机制是什么?为什么a.s打印的是“a”

字段引用不受多态性的约束,因此在编译时编译器正在引用A的字段,因为您的局部变量是A类型的

换句话说,字段行为类似于方法上的Java重载行为,而不是Java重写行为。

这不是多态性(标记)


Java没有虚拟成员变量(即不重写属性),而是将其隐藏。

您可能希望字段像方法一样被重写,并根据对象的运行时类型进行动态分派

Java不是这样工作的。字段不会被覆盖,而是被隐藏。这意味着类B的对象有两个名为“s”的字段,但访问哪一个字段取决于上下文


至于为什么会这样:重写字段是没有意义的,因为当类型不同时,没有有用的方法使其工作,当类型相同时也没有意义(因为您可以只使用超类字段)。就个人而言,我认为这应该只是一个编译器错误。

虽然成员变量是从基类继承的,但它们不是以多态方式调用的(即动态调用不适用于成员变量)

因此,a.s将引用基类中的成员,而不是派生类中的成员


话虽如此,代码并没有遵循OO原则。类的成员需要是私有的/受保护的(不是公共的或默认的),这取决于业务用例,并且您需要提供公共方法来获取和设置成员的值。

它不是属性,而是字段和成员变量。术语不严格,谢谢你的回答。我忽略了虚拟(继承的?)方法和成员之间的细微差别。阅读我链接的维基百科文章,了解虚拟方法是什么。除了其他回答外,请注意,如果不将a向下转换为B,就无法访问B的s成员,例如((B)a)。谢谢你的回答。看看我是否正确理解了这个概念。上下文意味着声明的类型?假设可以向上投射,我做了以下操作:B=新A();那么在b.s中应该打印“b”?因为这是不可能的,所以争论“应该”打印什么是没有意义的,但是是的,这是基本的想法。谢谢,我认为这澄清了很多事情!谢谢你的回答。如果可以的话,我想从您的回答中澄清以下内容:[1]在运行时和编译时,“a”所代表的内容是否有区别。[2] 在代码中的哪一点出现了实际的重载机制?错误,更正:[2]。。。。实际字段是否出现“重载”机制?=)@Krolique,A在编译时实际上并不包含任何内容(它只是一个定义,不是执行的代码)。在类B中定义变量s时会发生重载。此时,在两个不同的类中有两个同名的字段。编译器是决定在代码中引用哪一个的编译器。这不是动态的。谢谢你,我想这可以澄清很多事情!谢谢你的回答。在正常情况下,我会照你的建议去做。
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);
    }
}