在学些很多知识之后,再理解多态发现其中的含义
知识点:
1.向下转型
2.向上转型
3.instanceof关键字
4.动态绑定
5.静态绑定
无论是向上还是向下,二者都必须有继承关系。
1.父类型的引用指向子类型的对象-------向上转型(自动类型转换)
- Animal a2 = new Cat();
- a2.move(); // 猫在走猫步!!!
当使用父类引用调用方法时,本质上调用的是子类的方法。(前提是这个方法父类和子类都有)
从而引用两个概念:静态绑定,动态绑定,多态
多态:多种形态,多种状态。编译时一种形态,运行时另一种形态。
Java程序分为编译和运行两个阶段。
编译阶段:
对于编译器来说,他只认识引用,而不去new对象,只直到父类的引用类型是Animal,会去字节码文件中去找Animal的那个方法。找到之后,绑定上这个方法,编译成功,静态绑定成功。
运行阶段:
运行阶段的时候,实际上在堆内存中创建的是子类的对象,所有调用方法时,真正参与此方法的对象是子类对象,所以运行阶段会动态执行子类的方法。这个过程是动态绑定。
2.向下转型(强制类型转换)
首先说明为什么会有向下转型?哪里有痛点,哪里就有机会,hhhhhhha。
============================================
当我的子类中有了自己的独有方法时,以下代码是无法运行的。
- Animal a2 = new Cat();
- a2.move(); // 猫在走猫步!!!
- a2.catchMouse();
理论上我的子类是具有此方法的,但是你发现你无法 "." 出来,这是编译阶段的问题。
因为编译器只知道a2的类型是Animal,去Animal字节码(class)文件中去找catchMouse(),但是找不到,所以静态绑定失败。编译通不过。
综上,编译通不过,无法运行。编译不成功,无法运行。
====================================================
为了使用我子类独有方法,需要进行向下转型。
- Animal a2 = new Cat();
- Cat x=(Cat)a2;
- x.catchMouse(); // 猫在抓老鼠
但是,向下转型有风险。
- Animal a3 = new Dog();
- Cat c3 = (Cat)a3;
- c3.catchMouse();
此代码,编译没毛病,运行会报错!!! ClassCastException
分析:
编译没问题:
从第二行开始,编译器发现a2是Animal类型引用,并且Cat和Animal之间存在继承关系,可以向下转型没问题。c3是一个猫类,也确实有这个方法。
运行有问题:
堆内存中实际存在的是Bird对象,在实际运行中,无法将猫转为狗,因为二者没有继承关系。
如何避免ClassCastException的异常呢??
利用 instanceof 运算符。
其可以在运行阶段动态判断引用指向的对象的类型。
语法 (引用 instanceof 类型) 结果为true/false
即,此引用指向的堆内存的对象是一个Cat或者不是一个Cat。
- Animal a2 = new Cat();
- a2.move(); // 猫在走猫步!!!
-
- if(a2 instanceof Cat){
- Cat x=(Cat)a2;
- x.catchMouse(); // 猫在抓老鼠
- }
-
- Animal a3 = new Dog();
- // 判断不成立,不走下面的代码
- if(a3 instanceof Cat){
- Cat c3 = (Cat)a3;
- c3.catchMouse();
- }