先了解两个概念:向上转型和向下转型
向上转型
父类引用指向子类对象
这样做的意义是:
当我们需要多个同父的对象调用某个方法时,通过向上转换后,则可以确定参数的统一.方便程序设计。
向上转型的缺陷
animal a = new cat();
a.catchMouse();
a引用了子类猫的对象,编译器比较笨,它只会根据引用的类型去寻找字节码文件,于是它到animal.class中寻找catchMouse(抓老鼠这个方法),没有找到所以就报错了
向下转型
父类转型成子类就是向下转型
注意事项
无论是向上转型还是向下转型,都必须要求转型的两个类是有继承关系的。
例如
public class Demo {
public static void main(String[] args) {
animal a = new cat();
bird b = (bird)a;
b.catchMouse();
}
}
class animal{
public void speak(){
System.out.println("动物在叫");
}
}
class bird extends animal{
@Override
public void speak() {
System.out.println("鸟儿在叫");
}
}
class cat extends animal{
public void speak(){
System.out.println("猫在叫");
}
public void catchMouse(){
System.out.println("抓老鼠");
}
}
cat类和bird类都继承于animal类,但是cat类与bird类没有继承关系所以,上述代码会抛出异常
![]()
向下转型是用来解决向上转换的缺陷的。所以当我们想调用子类的特有方法时,为了使编译器不报错,需要让编译器去找子类的字节码,这样编译才能通过。
但是!!!! 编译通过了,运行阶段不一定通过!例如上面的b是一个cat类型的引用变量,但是a实际上是一个bird对象,而bird对象中没有catchMouse(),所以就会引发ClassCastException异常。
所以,使用向下转型的前提条件必须保证转型的两个类必须有继承关系(等号左边的引用和等号右边引用所指向的对象必须有继承关系)
如何避免ClassCastException异常
但是,有时候类多了,可能不好理清类与类之间的关系,JAVA提供了一个关键字instanceof来判断引用所指向的对象的类型
关于instancof有以下几点
- instanceof可以在运行阶段动态判断引用所指向的对象的类型
- instanceof的语法是 (引用 instanceof 类型)
- instanceof运算符的返回结果只能是:true/false
实际应用例子
public class Demo {
public static void main(String[] args) {
animal a = new cat();
if(a instanceof cat){
cat b = (cat)a;
b.catchMouse();
}
}
}
如果a引用指向的对象是一个cat类的对象,那么则进行向下转型
多态
首先看一个例子
鸟类和猫类继承于动物类,鸟和猫类中重写了动物类中的speak方法
当用一个cat类的引用变量 c去引用一个cat对象时,c.speak()方法输出的是 "猫在叫",那么我们用animal 类的引用变量C 去引用一个cat对象时,C.speak()方法输出的又是什么呢?
答案还是 "猫在叫",为什么呢?这就要引出多态的概念了
public class Demo {
public static void main(String[] args) {
//猫再叫
cat c = new cat();
c.speak();
//鸟在叫
bird b = new bird();
b.speak();
animal C = new cat();
animal B = new bird();
C.speak();
B.speak();
}
}
class animal{
public void speak(){
System.out.println("动物在叫");
}
}
class bird extends animal{
@Override
public void speak() {
System.out.println("鸟儿在叫");
}
}
class cat extends animal{
public void speak(){
System.out.println("猫在叫");
}
}
什么是多态
父类型引用指向子类型对象。包括编译阶段和运行阶段。
编译阶段:绑定父类的方法。
运行阶段:动态绑定子类型对象的方法
如何实现多态
分析C.speak();
java程序分为编译和运行阶段
编译阶段:对于编译器来说,编译器知道C的类型是animal,所以会在语法检查时去找animal.class中的speak()方法,找到了,绑定上speak()方法,编译通过,静态绑定成功。(编译阶段属于静态绑定)
运行阶段:运行阶段,实际上在堆内存中创建的对象时cat对象,所以speak()的时候,真正参与speak的对象是一只猫,所以运行阶段会动态执行cat对象的speak()方法。这个过程属于运行阶段绑定。(运行阶段绑定属于动态绑定)
多态表示多种形态:编译时候一种形态,运行时候另一种形态。
多态在开发中的作用
OCP
在软件开发中,有一条原则是OCP(开闭原则),即对扩展开放,对修改关闭。
意思是在软件的扩展过程中,修改的越少越好。
作用
降低程序的耦合度,提高程序的扩展力
使用多态,意味着我们可以使用父类的引用来指向子类的对象,可以在父类里设定一个方法,参数为父类的引用,每次传进子类的对象,再利用方法重写,去实现子类的相关功能。这样我们在扩展程序时候只需要加子类,而不需要修改父类,减少了对程序的修改。
164

被折叠的 条评论
为什么被折叠?



