Chinaunix首页 | 论坛 | 博客
  • 博客访问: 69958
  • 博文数量: 43
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 420
  • 用 户 组: 普通用户
  • 注册时间: 2014-06-27 15:04
个人简介

记录,分享

文章分类

全部博文(43)

文章存档

2017年(24)

2015年(1)

2014年(18)

我的朋友

分类: Java

2014-06-27 16:19:18

一、多态的概念

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) |
给主人留下些什么吧!~~