《疯狂Java讲义精粹》读书笔记2 多态

-----------------《疯狂Java讲义精粹》2读书笔记---------------

  Java引用变量有两个类型:

    · 编译时类型(由声明该变量时使用的类型决定)
    · 运行时类型(由实际赋给该变量的对象决定)

  编译时类型和运行时类型不一致,就可能出现多态(Polymorphism)。往往是相同类型的变量、调用同一个方法时呈现出多种不同的行为特征。

 

看下面这个例子:

 1 public class TestExtends extends BaseClass{
 2     public String book = "子类的book成员";
 3     public void test(){
 4         System.out.println("子类覆盖父类的test方法");
 5     }
 6     public void sub(){
 7         System.out.println("子类自己的方法");
 8     }
 9     
10     public static void main(String[] args) {
11         /**
12          * 子类其实是一种特殊的父类,因此Java允许把一个子类对象直接赋给一个父类引用,
13          * 无需仍和转换,或者称为向上转型(upcasting),由系统自动完成。
14          */
15         BaseClass bc = new TestExtends();//父类引用指向子类对象
16         System.out.println(bc.book);//调用父类的book
17         bc.base();//调用基类的普通方法
18         bc.test();//调用子类覆盖的方法
19         //bc.sub();//将会出错
20     }
21 }

结果为:

    6
  基类的普通方法....
  子类覆盖父类的test方法

  通过引用变量来访问其包含的实例成员时,系统总是访问它编译时所定义的成员,而不是运行时所定义的成员,即使它实际所引用的对象确实包含该方法。

例如上面的引用变量bc想调用运行时的成员方法sub(即bc.sub())时就会出错。

  那么怎么才能让这个引用变量调用它运行时的成员方法呢?
  其实很简单,只需要强制转换类型就可以了。也就是说:强制转换类型可以将一个引用类型的变量转换成其子类类型。当然,在执行强制转换类型时应当注意:
    · 基本类型的转换只能在数值类型(整形、字符型和浮点型)之间转换。数值类型和布尔类型之间不能进行类型转换。
    · 引用类型之间的转换只能在具有继承关系的两个类型之间转换。如果试图把一个父类型转换成子类类型,则这个对象必须实际上是子类实例才行(即编译时类型为父类型,而运行时类型为子类类型才行),否则会出现ClassCastException异常。

  例如:将上面的代码第19行进行强制类型转换从而调用子类的成员方法:

19 ((TestExtends) bc).sub();//转换后调用运行时的成员方法

运行的结果为:

   6
  基类的普通方法....
  子类覆盖父类的test方法
  子类自己的方法

  

原文地址:https://www.cnblogs.com/CocoonFan/p/2943663.html