一、多态的概念
java引用变量有两种类型:编译时类型和运行时类型。编译时类型由声明该变量时所用的类型决定,运行时类型由实际赋给该变量的对象决定。当编译类型与运行类型不一致时,就会出现所谓的多态(Polymophism)
二、多态的规则(参考:变量->5. 变量的赋值和类型转换,数据类型与操作符->instance of)
1.编译阶段: 对于一个引用类型的变量,编译器按照它声明的类型来处理。 java编译器允许在具有直接或间接继承关系的类之间进行类型转换。转换分自动转换和强制转换
-
自动转换:将子类变量赋值给直接或间接父类变量(如Dog变量赋给Animal变量),称为向上转型
-
强制转换:将父类赋值给子类或间接子类(如Animal变量赋值给Dog变量),称为向下转型
2. 执行阶段:对于一个引用类型的变量,运行时java虚拟机按照它实际引用的对象来处理。运行时,子类的对象可以转换成父类类型,而父类的对象(实际类型,非声明类型)实际上无法转换成子类类型。
关于以上两点,请看下面的代码:
Dog dog1 = new Dog();
Cat cat1 = (Cat)dog; //编译出错
Animal dog2= new Dog;
Cat cat2 =(Cat)dog2; //编译可以通过,但运行时抛出ClassCastException
Base who = new Base();
Sub sub = (Sub)who; //假定运行时没出错,可以进行强制转换
sub.subMethod(); //sub实际上引用的是Base类型的实例,而Base类可能没有subMethod方法,从而可能出错
3. 在运行时环境中,通过引用类型变量来访问所引用对象的方法和属性时,java虚拟机采用以下规则来将实例与方法(变量)进行绑定:
-
实例方法<->变量实际引用的对象的方法(动态绑定,运行时有虚拟机决定)
-
静态方法<->声明变量时所用类型的方法(静态绑定,编译阶段就已绑定)
-
成员变量<->声明变量时所用类型的成员变量(静态绑定,编译阶段就已绑定)
4.(针对3的第一条) 在运行时环境中,如果通过某个类的实例去调用实例方法时,会优先和该类本身的实例方法绑定,如果找不到该实例方法,则会向上与父类中的实例方法绑定。
public class Base(){
void method(){
System.out.println("base");
}
void test(){
method();
}
}
public class Sub extends Base{
void method(){ System.out.println("sub"); }
public static void main(String[] args){
new Base().test(); //1
new Sub().test(); //2
}
}
执行结果:base
sub
代码2处,Sub类自身没有test方法,该实例则向上绑定父类Base的test方法,test方法中调用method方法时,仍然优先与实例自身Sub类的method方法绑定,因此输出”sub“。
阅读(443) | 评论(0) | 转发(0) |