《疯狂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方法
子类自己的方法