向上转型(uqcasting):子类型–》父类型,自动类型转换
向下转型(downcasting):父类型–》子类型,强制类型转换
无论是向上还是向下,必须有继承关系。
public class Test {
public static void main(String[] args) {
Animal a1 = new Animal();
a1.move();
Cat c1 = new Cat();
c1.move();
c1.catchMouse();
Bird b1 = new Bird();
b1.move();
//使用多态
Animal a2 = new Cat();
a2.move();
}
public class Animal {
public void move() {
System.out.println("动物在移动");
}
}
public class Cat extends Animal{
//重写父类继承过来的方法
public void move() {
System.out.println("猫在走猫步");
}
//不是继承的,子类特有的
public void catchMouse() {
System.out.println("猫抓老鼠");
}
}
public class Bird extends Animal {
public void move() {
System.out.println("鸟在飞");
}
public void fly() {
System.out.println("fly");
}
}
}
Animal a2 = new Cat();
Animal与Cat是继承关系,Animal是父类,Cat是子类。new Cat()创建的对象是Cat,a2这个引用的数据类型是Animal,可见他们进行了类型转换,子类型转换父类型。Java中允许父类型引用指向子类型对象。
Java程序分为编译阶段和运行阶段,先编译,失败无法运行。编译阶段检查a2这个引用数据类型是Animal,由于Animal.class字节码中只有move()方法,所以编译通过,这个过程叫静态绑定,编译阶段绑定,只有静态绑定通过裁员后续。
在运行阶段,jvm堆内存中真实存在的是cat对象,那么程序运行阶段一定会调用cat对象的move()方法,叫程序的动态绑定,运行阶段绑定。
a2.catchMouse();不能调用:编译阶段检查到a2是Animal类型,在Animal.class中没有找到该方法,导致静态绑定失败,编译失败,不运行。
Cat c2 = (Cat)a2;
Animal a3 = new Bird();
/**
* 以下程序编译没问题,因为编译器检查到a3的数据类型是Animal
* Animal和Cat之间存在继承关系,并且Animal是父类型,Cat是子类型
* 父类型转换为子类型叫做向下转型,语法合格。
* 编译通过,但程序在运行阶段会出现异常,因为jvm堆内存中真实存在的对象是Bird类型,无法转换为Cat对象
* 因为两种类型之间不存在任何继承关系,此时出现著名异常:
* java.lang.ClassCastException
* 类型转换异常,总是发生在"向下转型"的时候发生
*/
//Cat c3 = (Cat)a3;
/**
* 以上异常只有在强制类型转换的时候,向下转型存在隐患
* 向上转型只要编译通过 ,运行一定不会出现问题。Animal a2 = new Cat();
* 向下转型编译通过,运行可能错误。Animal a3 = new Bird();Cat c3 = (Cat)a3;
* 怎么避免?
* 使用instanceof运算符。语法:(引用 instanceof 数据类型名)结果可能是true/false
* 假设:(a instanceof Animal)true表示指向的对象是一个Animal类型,false不是
*/
if(a3 instanceof Cat) {
Cat c3 = (Cat)a3;
}else if(a3 instanceof Bird) {
Bird b2 = (Bird)a3;
b2.fly();
}
}