-
向上转型(upcasting)和向下转型(downcasting)
-
向上转型:
-
子类——>父类,即自动类型转换
-
-
向下转型:
-
父类——>子类,即强制类型转换【需要加强制类型转换符】
-
需要访问/调用子类对象中”特有“的方法,才用向下转型
-
-
两类型之间必须要有继承关系,没有继承关系编译无法通过
-
-
何为多态
-
多态指的是:父类型引用指向子类型对象,包括编译阶段和运行阶段
-
编译阶段绑定父类方法,运行阶段绑定子类型对象的方法
-
-
instanceof运算符
-
java.lang.ClassCastException:类型转换
-
java.lang.NullPionterExpception:空指针异常
-
instanceof可以在运行阶段动态判断引用指向的对象的类型
-
instanceof的语法:【引用instanceof类型】
-
instanceof运算符的结果只能是:true/false
-
c是一个引用,c变量保存了内存地址指向了堆中的对象,例子看下面代码的行
-
无论何时何地,对类型进行向下转型时,要使用instanceof运算符进行判断,好避免ClassCastException\
-
package com.two.mebb;
public class Animal01 {//父类
public void move() {
System.out.println("动物在移动");
}
}
package com.two.meaa;
import com.two.mebb.Animal01;
public class Cat01 extends Animal01 {//子类
public void move() {
System.out.println("猫在移动");
}
//猫自己特有的行为,即子类型特有的方法
public void eat() {
System.out.println("猫吃老鼠");
}
}
package com.two.meaa;
import com.two.mebb.Animal01;
public class Bird01 extends Animal01 {//子类
public void move() {
System.out.println("鸟在飞翔");
}
}
package com.two.me;
import com.two.meaa.Bird01;
import com.two.meaa.Cat01;
import com.two.mebb.Animal01;
public class DuoTest01 {
public static void main(String[] args) {
Animal01 a1 = new Animal01();
a1.move();//动物在移动
Cat01 c1 = new Cat01();
c1.move();//猫在移动
Bird01 b1 = new Bird01();
b1.move();//鸟在飞翔
//换种写法
Animal01 a2 = new Cat01();
/*父类型的引用允许指向子类型的对象
a2就是父类型的引用
new Cat01()是一个子类型的对象
*/
a2.move();//猫在移动
/*什么是多态?分析a2.move();
* java程序分为编译阶段和运行阶段,
* 对编译阶段:
* 对编译器来说,编译器只知道a2的类型是Animal
* 所以编译器在检查语法时,会去Animal。class字节码文件中找move方法
* 找到了就绑定上move()方法,编译通过,静态绑定成功(编译阶段属于静态绑定)
* 再是运行阶段:
* 此时,实际上的堆内存中创建的java对象是Cat对象,所以move的时候
* 真正参与move的对象是一只猫
* 所以运行阶段会动态执行Cat对象的move()方法
* 此过程称为动态绑定
* */
Animal01 a3 = new Cat01();
Cat01 x = (Cat01)a3;//进行强转
x.eat();
/*a3.eat();不行,why?
* 因为编译器只知道a3是Animal01类型
* 去Animal01.class文件找eat()方法找不到
* 静态绑定失败,编译报错,无法运行
* 只有编译通过的代码才能运行,编译不通过,就轮不到运行
* */
/*Animal01 a4 = new Bird01();
* Bird01 y = (Bird01)a4;
* y.eat();
* 编译器检测到的a4这个引用是Animal01类型
* 而Animal01与Cat之间存在继承关系,所以可以向下转型,编译没问题,
* 运行阶段,堆内存实际创建的对象是Bird01对象,
*
*c是一个引用,c变量保存了内存地址指向了堆中的对象
*假设(c instanceof Cat)为true表示:c引用指向的堆内存中的java对象是一个Cat
*假设(C instanceof Cat)为false表示:c引用指向的堆内存中的java对象不是一个Cat
*
* */
Animal01 a4 = new Bird01();
System.out.println(a4 instanceof Cat01);//false
if(a4 instanceof Cat01){//如果a4是一只Cat
Cat01 y = (Cat01)a4;//再进行强制类型转换
y.eat();
}
/*疑问:肉眼可以看到底层到底是new Bird01()还是new Cat01(),
* 为什么还要进行instanceof的判断?
* 因为,以后可能肉眼看不到
* */
}
}