父类型引用 指向 子类型对象。
关于java语言当中的多态语法机制:
Animal,Cat,Bird 三个类之间的关系
Cat 继承 Animal
Bird 继承 Animal
Cat 和 Bird 之间 没有任何继承关系
面向对象三大特征:封装 继承 多态
多态当中涉及到的概念:
向上转型(upcasting)
子类型--->父类型
又称为: 自动类型转换
向下转型(downcasting)
父类型--->子类型
又称为: 强制类型转换(需要 强制类型转换符)
两种类型之间必须存在继承关系(无论是 向上 还是 向下)
public class Animal {
// 移动
public void move(){
System.out.println("动物在移动");
}
}
// 鸟类
public class Bird extends Animal {
// 重写从父类继承过来的方法
public void move(){
System.out.println("鸟在飞翔");
}
}
// Cat
public class Cat extends Animal {
// 重写父类继承过来的方法
public void move(){
System.out.println("猫在在跳");
}
// 不是从父类中继承过来的
public void catchMouse(){
System.out.println("猫抓老鼠!");
}
}
/*
关于java语言当中的多态语法机制:
Animal,Cat,Bird 三个类之间的关系
Cat 继承 Animal
Bird 继承 Animal
Cat 和 Bird 之间 没有任何继承关系
面向对象三大特征:封装 继承 多态
多态当中涉及到的概念:
向上转型(upcasting)
子类型--->父类型
又称为: 自动类型转换
向下转型(downcasting)
父类型--->子类型
又称为: 强制类型转换(需要 强制类型转换符)
两种类型之间必须存在继承关系(无论是 向上 还是 向下)
*/
public class Test {
public static void main(String[] args) {
// 以前写的程序
Animal a1 = new Animal();
a1.move();
Cat c1 = new Cat();
c1.move();
Bird b1 = new Bird();
b1.move();
// 多态机制
// Animal 和 Cat之间存在 继承关系,Animal是父类,Cat是子类
// new Cat() 创建的对象的类型是Cat,a2这个引用的数据类型是Animal,可见它们进行了类型转换
Animal a2 = new Cat(); // 子类转父类,向上转型,自动转换类型,父类型引用 指向 子类型对象
/*
java程序永远分为 编译阶段 和 运行阶段
先分析 编译阶段, 再分析 运行阶段, 编译无法通过,是根本无法运行。
编译阶段 编译器 检查a2 引用的类型 为 Animal,由于 Animal.clas
字节码当中有move()方法,所以编译通过了,这个过程,我们称之为 静态绑定,编译阶段绑定、
只有静态绑定成功之后,才会有后续的运行。
在程序运行阶段,JVM内存当中 真实创建的对象是Cat对象,那么以下程序是在运行阶段
一定会调用Cat对象的move()方法,此时发生了程序的动态绑定,运行阶段绑定、
*/
a2.move(); // 这个时候,a2只会被当做animal类
// 多态是指,编译期 和 运行期 程序处于两个不同的状态
// 无论cat有没有重写move方法,运行阶段一定调用的是cat对象的move方法,因为底层的真是对象就是Cat对象。
// 父类型引用 指向 子类型对象 这种机制导致程序存在 编译阶段绑定 和 运行阶段绑定 两种不同的形态/状态、
// a2.catMouse(); Animal不能使用 Cat的方法
// 以上程序不能调用 是因为 编译阶段 编译器 查到a2的类型是Animal类型
// 从Animal.class字节码文件当中 查找到catchMuouse()方法,
// 最终没有找到该方法,导致静态绑定失败,没有绑定成功,也就是说编译失败了。别谈运行了。
// 强制类型转换:将a2从 Animal 转换为 Cat 可以让 a2这个对象 执行 catchMouse()方法
// 向下转型,两者之间得有继承关系,必须加 强制类型转换。
// 当调用的方法是 子类型中特有的,在父类型中不存在,必须进行 向下转型。
Cat c2 = (Cat) a2;
/*
long x = 100L;
int i = (int)x;
*/
}
}
重写鸟类
// 鸟类
public class Bird extends Animal {
// 重写从父类继承过来的方法
public void move(){
System.out.println("鸟在飞翔");
}
public void fly(){
System.out.println("Bird Fly!");
}
}
/*
关于java语言当中的多态语法机制:
Animal,Cat,Bird 三个类之间的关系
Cat 继承 Animal
Bird 继承 Animal
Cat 和 Bird 之间 没有任何继承关系
面向对象三大特征:封装 继承 多态
多态当中涉及到的概念:
向上转型(upcasting)
子类型--->父类型
又称为: 自动类型转换
向下转型(downcasting)
父类型--->子类型
又称为: 强制类型转换(需要 强制类型转换符)
两种类型之间必须存在继承关系(无论是 向上 还是 向下)
*/
public class Test {
public static void main(String[] args) {
// 以前写的程序
Animal a1 = new Animal();
a1.move();
Cat c1 = new Cat();
c1.move();
Bird b1 = new Bird();
b1.move();
// 多态机制
// Animal 和 Cat之间存在 继承关系,Animal是父类,Cat是子类
// new Cat() 创建的对象的类型是Cat,a2这个引用的数据类型是Animal,可见它们进行了类型转换
Animal a2 = new Cat(); // 子类转父类,向上转型,自动转换类型,父类型引用 指向 子类型对象
/*
java程序永远分为 编译阶段 和 运行阶段
先分析 编译阶段, 再分析 运行阶段, 编译无法通过,是根本无法运行。
编译阶段 编译器 检查a2 引用的类型 为 Animal,由于 Animal.clas
字节码当中有move()方法,所以编译通过了,这个过程,我们称之为 静态绑定,编译阶段绑定、
只有静态绑定成功之后,才会有后续的运行。
在程序运行阶段,JVM内存当中 真实创建的对象是Cat对象,那么以下程序是在运行阶段
一定会调用Cat对象的move()方法,此时发生了程序的动态绑定,运行阶段绑定、
*/
a2.move(); // 这个时候,a2只会被当做animal类
// 多态是指,编译期 和 运行期 程序处于两个不同的状态
// 无论cat有没有重写move方法,运行阶段一定调用的是cat对象的move方法,因为底层的真是对象就是Cat对象。
// 父类型引用 指向 子类型对象 这种机制导致程序存在 编译阶段绑定 和 运行阶段绑定 两种不同的形态/状态、
// a2.catMouse(); Animal不能使用 Cat的方法
// 以上程序不能调用 是因为 编译阶段 编译器 查到a2的类型是Animal类型
// 从Animal.class字节码文件当中 查找到catchMuouse()方法,
// 最终没有找到该方法,导致静态绑定失败,没有绑定成功,也就是说编译失败了。别谈运行了。
// 强制类型转换:将a2从 Animal 转换为 Cat 可以让 a2这个对象 执行 catchMouse()方法
// 向下转型,两者之间得有继承关系,必须加 强制类型转换。
// 当调用的方法是 子类型中特有的,在父类型中不存在,必须进行 向下转型。
Cat c2 = (Cat) a2;
/*
long x = 100L;
int i = (int)x;
*/
Animal a3 = new Bird(); // 父类型引用 指向 子类型对象
// Cat c3 = (Cat) a3; //error:Bird cannot be cast to Cat
// 上面一行的程序编译没问题。因为编译器 检查到a3的数据类型是 Animal
// Animal 和 Cat之间存在 继承关系,并且Animal是 父类型, Cat是 子类型
// 父类 转换 子类 叫做 向下转换, 语法合格。
// 程序虽然编译通过了,但是程序在运行阶段会出现异常,因为JVM堆内存当中真实存在的对象是Bird类型。
// Bird类型的对象 无法 转换为 Cat对象,因为两种类型之间不存在任何继承关系,此时出现了著名的异常。
// 以上异常只有在强制类型转换的时候才会发生, "向下转型" 存在隐患(编译过了,但是运行错了)
// 向上转型 编译通过,运行一定不会出问题: Animal a = new Cat();
// 向下转型 编译通过,运行可能会出错: Animal a3 = new Bird(); Cat c3 = (Cat) a3;
// 如何避免向下转型,出现的classCastException异常:
// 使用instance运算符 可以避免出现以上的异常。
// 语法格式: (引用 instanceof 数据类型名)
// 以上运算符的执行结果类型可能是布尔类型,结果可能为true,也可能为false。
// 假设(a instance of Animal):
// true: a 这个引用指向的对象 是一个 Animal类型
// false: a 这个引用指向的对象 不是一个 Animal类型
//在进行强制类型转换之前,采用 instanceof 进行类型的判断
// 当a3的引用指向的对象确实是Cat的时候,才执行
if (a3 instanceof Cat){ //a3 是否是 一个Cat类型的对象
Cat c3 = (Cat) a3;
c3.catchMouse();
} else if (a3 instanceof Bird){ //a3 是否是 一个Bird类型的对象
Bird b2 = (Bird) a3;
b2.fly();
}
}
}
/*
关于java语言当中的多态语法机制:
Animal,Cat,Bird 三个类之间的关系
Cat 继承 Animal
Bird 继承 Animal
Cat 和 Bird 之间 没有任何继承关系
面向对象三大特征:封装 继承 多态
多态当中涉及到的概念:
向上转型(upcasting)
子类型--->父类型
又称为: 自动类型转换
向下转型(downcasting)
父类型--->子类型
又称为: 强制类型转换(需要 强制类型转换符)
两种类型之间必须存在继承关系(无论是 向上 还是 向下)
*/
public class Test {
public static void main(String[] args) {
// 父类型引用指向子类型对象
// 向上转型
Animal a1 = new Cat();
Animal a2 = new Bird();
// 向下转型「只有放访问子类型对象中特有的方法」
if (a1 instanceof Cat){
Cat c1 = (Cat) a1;
c1.catchMouse();
} else if (a1 instanceof Bird){
Bird b1 = (Bird) a2;
b1.fly();
}
}
}
主人喂养宠物
主人
public class Master {
// 主人喂养宠物
public void feed(Cat c){
c.eat();
}
}
猫
// Cat
public class Cat {
public void eat(){
System.out.println("小猫正在吃鱼!");
}
}
交互
/*
以主人喂养宠物为例子,说明多态的作用:
主人[类]
主人可以喂养宠物,所以主人 可以 有 喂养 动作
宠物[类]
宠物可以吃东西, 所以从无 可以 有 吃东西 动作
2、面向对象编程的核心:定义好类,让类实例化为对象,给一个环境趋势一下,让各个对象之间协作形成系统。
*/
public class Test {
public static void main(String[] args) {
//创建主人对象
Master zs = new Master();
//创建猫对象
Cat tom = new Cat();
//主人喂养猫
zs.feed(tom);
}
}
增加狗对象
public class Dog{
public void eat(){
System.out.println("小狗正在啃骨头!");
}
}
得修改人
public class Master {
// 主人喂养宠物
public void feed(Cat c){
c.eat();
}
public void feed(Dog d){
d.eat();
}
}
测试
public class Test {
public static void main(String[] args) {
//创建主人对象
Master zs = new Master();
//创建猫对象
Cat tom = new Cat();
//主人喂养猫
zs.feed(tom);
//创建小狗
Dog xg = new Dog();
//主人喂养小狗
zs.feed(xg);
}
}
程序编译期,调用的是Pet方法,但是程序运行期,调用的是Cat和Dog方法。
通过多态,降低程序的耦合度,提高升序的扩展力。
能使用多态,尽量使用多态。
父类型引用指向 子类型对象。
public class Master {
// 主人喂养宠物
// master主人类面向的是一个抽象的Pet,不再面向具体的宠物。
public void feed(Pet c){ //这里Pet pet 是一个父类型的引用
c.eat();
}
}
public class Cat extends Pet{
public void eat(){
System.out.println("小猫爱吃鱼!");
}
}
public class Dog extends Pet{
public void eat(){
System.out.println("小狗正在啃骨头!");
}
}
public class Snake extends Pet{
public void eat(){
System.out.println("蛇在吃东西!");
}
}
public class Pet {
// 所有的宠物都可以吃东西
public void eat(){
}
}
/*
以主人喂养宠物为例子,说明多态的作用:
主人[类]
主人可以喂养宠物,所以主人 可以 有 喂养 动作
宠物[类]
宠物可以吃东西, 所以从无 可以 有 吃东西 动作
2、面向对象编程的核心:定义好类,让类实例化为对象,给一个环境趋势一下,让各个对象之间协作形成系统。
*/
public class Test {
public static void main(String[] args) {
//创建主人对象
Master zs = new Master();
//创建猫对象
Cat tom = new Cat();
//主人喂养猫
zs.feed(tom); //这个父类型的引用指向的是 子类型的变量
//创建小狗
Dog xg = new Dog();
//主人喂养小狗
zs.feed(xg); //这个父类型的引用指向的是 子类型的变量
//创建蟒蛇
Snake ms = new Snake();
zs.feed(ms);
}
}