当把一个子类对象直接赋给父类引用变量时,编译时类型是父类类型,运行时类型是子类类型。当运行时调用该引用变量的方法时,其方法行为总是子类方法的行为,而不是父类方法行为,所以就出现了相同类型的变量,执行同一个方法时出现不同的行为特征,这就是多态。也就是说程序中定义的引用变量所指向的具体类型和通过该引用变量调用方法在编译时不确定,必须等到运行时才能确定。
实现多态的三个必要条件:
- 继承
- 重写
- 向上转型
有三种方法是没办法表现多态的,因为没法重写:
- static方法,因为static方法属于类,不属于实例,没法被继承,更不能被重写
- final方法,无法被子类重写
- private和protected方法,private方法对子类不可见,protected方法虽然可以被子类重写,但不能被外部所见,多态就无从谈起了。
实现多态的形式:
- 基于继承实现的多态, 主要表现在多个子类对同一方法的重写。
- 基于接口实现的多态, 是通过实现接口并覆盖接口中同一个方法的不同类来体现的。
多态的分类:
- 编译时多态,即方法的重载
- 运行时多态,即方法的重写
引用变量在编译阶段只能调用其编译时类型所具有的方法,但是运行时执行它运行时类型所具有的方法。因此,引用变量只能调用声明该变量时所用类里包涵的方法。
- 强制类型转换
如果需要让一个引用变量调用它运行时类型的方法(即子类的方法),则必须把这个引用变量强制类型转换为运行时类型,但在转换之前,最好先用instanceof 运算符判断是否可以成功转换,从而避免出现ClassCastException:
eg.
if (objPri instanceof String) { String str = (String)objPri; }
instanceof运算符前一个操作符通常是一个引用对象,后一个操作符是一个类或接口,它用于判断前面的对象是否是后面的类,或者其子类、实现类的实例。是返回true,不是返回false。
instanceof运算符前面操作符的编译时类型要么与后面的类相同,要么是后面类的子类,否则会引起编译错误。