首先,对于JVM实现引用的一个机制是:类实例的引用就是指向一个句柄(handle)的指针,这个句柄就是一堆指针:一个指针指向一块从java堆中为分配出来内存空间;另一个指针指向一张表(实际上这个表格也有两个指针(一个指针指向一个包含了对象的方法表,另外一个指向类对象,表明该对象所属的类型))
下面举例进行分析: Student st=new Student();//Student为子类
Person p=st;//Person 为超类
p.sayHello();//该方法在超类和子类中都存在
分析: * 为什么子类的类型的对象实例可以覆给超类引用? 自动实现向上转型。通过该语句,编译器自动将子类实例向上移动,成为通用类型Person; *p.sayHello()将执行子类还是父类定义的方法? 子类的。在运行时期,将根据p这个对象引用实际的类型来获取对应的方法。所以才有多态性。一个超类的对象引用,被赋予不同的子类对象引用,执行该方法时,将表现出不同的行为。 特别注意的是: 在p=st的时候,仍然是存在两个句柄,p和st,但是p和st拥有同一块数据内存块和不同的函数表。 动态链接:当父类中的一个方法只有在父类中定义而在子类中没有重写的情况下,才可以被父类类型的引用调用; 对于父类中定义的方法,如果子类中重写了该方法,那么父类类型的引用将会调用子类中的这个方法,这就是动态连接。总结它为:
一、使用超类型的引用指向子类的对象;
二、该引用只能调用超类中定义的方法和变量;
三、如果子类中重写了超类中的一个方法,那么在调用这个方法的时候,将会调用子类中的这个方法;(动态连接、动态调用)
四、变量不能被重写(覆盖),”重写“的概念只针对方法,如果在子类中”重写“了基类中的变量,那么在编译时会报错。 通过将子类对象引用赋值给超类对象引用变量来实现动态方法调用。 java 的这种机制遵循一个原则:当超类对象引用变量引用子类对象时,被引用对象的类型而不是引用变量的类型决定了调用谁的成员方法,但是这个被调用的方法必须是在超类中定义过的,也就是说被子类覆盖的方法。 1. 如果a是类A的一个引用,那么,a可以指向类A的一个实例,或者说指向类A的一个子类。 2. 如果a是接口A的一个引用,那么,a必须指向实现了接口A的一个类的实例。