Java中,如果有一个类型为A的引用变量a,赋给它的一个类型为B的对象是可行的:
A a = new B();
满足以下任一:
1.A是一个类;B是A的子类;
2.A是一个接口,B或者它的一个父接口实现A。B是实现A的另一个类的子类。
——向上转换。
如上的代码赋给a一个B的实例时,a的类型为A。这表示不能在B中调用在A中没用定义过的方法。(子类B可以有父类A中没有的方法);
但输出a.getClass().getName()的值,将会得到“B”而不是“A”。
这是因为:
1.编译时,a的类型为A,因此编译器不允许调用B中没有在A中定义的方法;
2.运行时,a的类型为B,如a.getClass().getName()所示;
这即是多态的本质:
如果B覆盖了A中的方法(比如一个名为play的方法),那么调用a.play()将导致调用B中play()的实现(不是A中的play);
多态使得在调用方法是对象能决定选择哪个方法实现(或是A中的play,或是B中的play);多态指示了在运行时调用的对象实现,但多态的作用远不止此。
多态是一个OOP特性,它使对象在接受到方法调用时能决定调用那哟个方法实现。
技术实现:
编译器遇到如a.paly()时,会检验a表示的这个类、接口是否定义了方法,是否给这个方法传递了更多的参数,不过编译器最多只做到这一步,除了静态方法和final方法外,它不会将方法调用和方法体连接(绑定起来),在运行时,JVM将决定怎样将方法调用和方法体进行绑定。
换句话说,除了静态方法和final之外,Java的方法绑定发生在运行时而不是编译时。称为后期绑定或者动态绑定。