为什么向上转换不显示运行时多态性?

时间:2014-01-18 09:24:45

标签: java polymorphism

我写了一段代码来了解运行时多态性......

class S{
     int i=1;
    void m(){
        System.out.println("sssssssssssssssssssss");
    }
}
public class A extends S{

    int i=2;

    void m(){
        System.out.println("aaaaaaaaaaaaaaaaaaaaaaaa");
    }

    public static void main(String[] args) {
        S a=(S)new A();
        System.out.println(a.i);
        a.m();
    }
} 

实例变量受编译时绑定的影响,但是为什么A的对象的向下转换在这里没有意义?意味着它调用A's方法而非S's方法?

2 个答案:

答案 0 :(得分:2)

S a = (S)new A();

让我们看看你在这里有什么:

  1. 变量a引用类型 S;
  2. 实例创建表达式,产生A类型的对象,其中A extends S;
  3. 引用转发表达式,将上述表达式向上转换为S类型;
  4. 将结果3分配到变量a
  5. 在阅读Java时,您必须清楚地了解以下内容:

    • 对象的类型:对象永远不能更改其类型。在您的示例中,对象的类型为A;
    • 类型的引用:在您的示例中,您最初将类型为A的引用转换为类型为S的引用。您已将该引用分配给a

    当您在对象上调用方法时,调用的实际方法根本不依赖于引用的类型,而只取决于对象的类型本身。对象的类型为A,因此调用类型A中的方法。

    另一方面,当您访问实例变量时,多态性不适用,并且引用的类型变得必不可少。使用a.i,您可以访问超类型i中声明的S,并使用((A)a).i访问来自i的{​​{1}}。请注意,类A拥有两个实例变量,两者都名为A,您可以单独引用它们。


    关于术语的说明

    术语“引用的类型”实际上是更正确的“产生引用的表达类型”的简写。它是纯粹的编译时工件:在运行时没有与引用关联的类型信息,它只是一个位模式。将此与对象的类型进行对比,该对象是纯粹的运行时工件:编译器通常不知道表达式中涉及的对象的类型,它只会使断言

答案 1 :(得分:0)

变量a是类型为S的引用,其类为A。当您在该对象上调用m()时,您将始终在调用类m()中获取A的版本,因为这是对象的类,无论哪种类型的变量是引用它。这就是多态性的含义。被调用的m()版本取决于对象的,而不是引用表达式的类型

但是,此对象实际上包含两个名为i的变量 - 一个在类A中声明,另一个在类S中声明。您获得哪一项取决于您使用的类型的引用表达式。由于变量a的类型为S,因此表达式a.i指的是在类S中声明的那个。