Java 为什么不是';是否根据对象的运行时类型选择此方法?

Java 为什么不是';是否根据对象的运行时类型选择此方法?,java,methods,overriding,Java,Methods,Overriding,考虑这一点: class A { int x =5; } class B extends A{ int x =6; } public class CovariantTest { public A getObject() { return new A(); } /** * @param args the command line arguments */ public static void

考虑这一点:

class A  {
    int x =5;
}

class B extends A{
        int x =6;
    }
public class CovariantTest {

    public A getObject() {
        return new A();
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        // TODO code application logic here
        CovariantTest c1 = new SubCovariantTest();
        System.out.println(c1.getObject().x);
    }

}

class SubCovariantTest extends CovariantTest {
    public B getObject(){
        return new B();
    }
}
据我所知,JVM根据其对象的真实类型选择方法。这里真正的类型是SubCoventTest,它定义了一个重写方法getObject


程序打印5,而不是6。为什么?

方法确实是由对象的运行时类型选择的。运行时类型未选择的是整数字段
x
B
对象有两个
x
副本,一个用于
A.x
,另一个用于
B.x
。您正在静态地从
A
类中选择字段,因为
getObject
返回的对象的编译时类型是
A
。可以通过向
a
B
添加方法来验证这一事实:

class A  {
    public String print() {
        return "A";
    }
}

class B extends A {
    public String print() {
        return "B";
    }
}
并将测试表达式更改为:

System.out.println(c1.getObject().print());

方法确实是由对象的运行时类型选择的。运行时类型未选择的是整数字段
x
B
对象有两个
x
副本,一个用于
A.x
,另一个用于
B.x
。您正在静态地从
A
类中选择字段,因为
getObject
返回的对象的编译时类型是
A
。可以通过向
a
B
添加方法来验证这一事实:

class A  {
    public String print() {
        return "A";
    }
}

class B extends A {
    public String print() {
        return "B";
    }
}
并将测试表达式更改为:

System.out.println(c1.getObject().print());

除非我弄错了,否则默认情况下java中的方法是虚拟的,因此您正确地重写了该方法。但是,字段(如“x”)不是虚拟的,不能重写。当您在B中声明“intx”时,实际上是在创建一个全新的变量


多态性不会对字段生效,因此当您尝试在强制转换为类型A的对象上检索x时,您将得到5,如果该对象强制转换为类型B,您将得到6。

除非我弄错了,否则默认情况下java中的方法是虚拟的,因此您正确地重写了该方法。但是,字段(如“x”)不是虚拟的,不能重写。当您在B中声明“intx”时,实际上是在创建一个全新的变量


多态性对字段不起作用,因此当您尝试在转换为类型A的对象上检索x时,您将得到5,如果对象转换为类型B,您将得到6。

当超级类和子类中的字段具有相同的名称时,它被称为“隐藏”。除了问答中提到的问题外,还有其他方面可能引起微妙的问题:

在类中,具有 与超类中的字段同名 隐藏超类的字段,即使 它们的类型不同。在 子类,超类中的字段 不能由其简单 名称相反,字段必须是 通过超级访问,这是 将在下一节中介绍。通常地 说实话,我们不建议躲起来 字段,因为它使代码难以 阅读


当超级类和子类中的字段名称相同时,一些编译器会警告不要隐藏变量,这称为“隐藏”。除了问答中提到的问题外,还有其他方面可能引起微妙的问题:

在类中,具有 与超类中的字段同名 隐藏超类的字段,即使 它们的类型不同。在 子类,超类中的字段 不能由其简单 名称相反,字段必须是 通过超级访问,这是 将在下一节中介绍。通常地 说实话,我们不建议躲起来 字段,因为它使代码难以 阅读


有些编译器会警告不要隐藏变量

你解释得比我好得多。。。这实际上是一个很难用语言表达的问题…你解释的比我好得多。。。这实际上是一个很难用词表达的问题。。。