JavaSE第十三章 多态
程序员文章站
2022-06-21 13:38:58
Java自我学习路线一、多态的基础语法1. 什么是多态2. 向上转型2.1 什么是向上转型3. 向下转型3.1 什么是向下转型3.2 什么时候向下转型3.3 向下转型的风险3.3.1 instanceof二、多态的作用1. 作用2. 开闭原则3. 简述面向对象三大特征三、多态存在的三个必要条件四、多态的实现方式一、多态的基础语法1. 什么是多态多态是同一个行为具有多个不同表现形式或形态的能力,即父类型引用指向子类型对象,期间包括编译阶段和运行阶段,编译阶段绑定父类型的方法(静态绑定),运行阶段绑定子...
Java自我学习路线
一、多态的基础语法
1. 什么是多态
- 多态是同一个行为具有多个不同表现形式或形态的能力,即父类型引用指向子类型对象,期间包括编译阶段和运行阶段,编译阶段绑定父类型的方法(静态绑定),运行阶段绑定子类型对象的方法(动态绑定)
2. 向上转型
Java中允许向上转型,也允许向下转型,但无论是向上转型还是向下转型,两种类型之间必须有继承关系,否则编译报错
2.1 什么是向上转型
- 子—>父 (upcasting)
Animal animal = new Dog();
对比基本数据类型的自动类型转换学习(小转大)
3. 向下转型
Java中允许向上转型,也允许向下转型,但无论是向上转型还是向下转型,两种类型之间必须有继承关系,否则编译报错
3.1 什么是向下转型
- 父—>子 (downcasting)
Dog dog = (Dog)animal; 需要添加强制类型转换符
对比基本数据类型的强制类型转换学习(大转小)
3.2 什么时候向下转型
- 需要调用或者执行子类对象中特有的方法
3.3 向下转型的风险
- 容易出现 ClassCastException(类型转换异常)
- 如何避免:
向下转型之前使用 instanceof 运算符进行判断,以此来确定某个引用指向的对象是否为某一种类型
3.3.1 instanceof
- instanceof 可以在运行阶段动态判断引用指向的对象的类型
- instanceof 的语法
引用 instanceof 类型
- instanceof 运算符的结果只能是 true/false
二、多态的作用
1. 作用
- 降低程序的耦合度,提高程序的扩展力
2. 开闭原则
- OCP:对扩展开放,对修改关闭(目的:降低程序的耦合度,提高程序的扩展力)
3. 简述面向对象三大特征
- 有了封装,对象与对象之间产生了继承,有了继承之后,才有了方法的重写和多态
- 封装:安全性和重用性
- 继承:高效性和重用性
- 多态:统一性和高效性
三、多态存在的三个必要条件
- 继承
- 重写
- 父类引用指向子类对象
四、多态的实现方式
- 重载、重写
- 接口(接口定义方法,方法的实现在继承接口的具体类中定义)
- 抽象类和抽象方法
public class Animal {
public void move() {
System.out.println("Animal move...");
}
}
public class Dog extends Animal {
// 重写父类的move方法
@Override
public void move() {
System.out.println("Dog run...");
}
//Dog特有的方法
public void run() {
System.out.println("Dog run...");
}
}
public class Bird extends Animal {
//重写父类的move方法
@Override
public void move() {
System.out.println("Bird fly...");
}
//Bird特有的方法
public void sing() {
System.out.println("Bird sing...");
}
}
public class AnimalTest {
public static void main(String[] args) {
// 创建对象
Animal animal = new Animal();
Bird bird = new Bird();
Dog dog = new Dog();
animal.move(); // Animal move...
bird.move(); // Bird fly...
dog.move(); // Dog run...
System.out.println("=================");
// 父类型的引用animal2指向子类型的对象new Dog()
// 这是向上转型(前提条件:存在继承关系)
Animal animal2 = new Dog();
Animal animal3 = new Bird();
/*
* 实现多态(编译和运行每种形态) Java程序分为编译阶段和运行阶段 编译阶段(静态绑定父类型的方法):
* 对于编译器来说,编译器只知道animal2和animal3的类型是Animal, 所以编译器在检查语法的时候,会去Animal.class字节码文件中
* 找move()方法,找到并绑定上move()方法,编译通过,静态绑定成功
*
* 运行阶段(动态绑定子类型的方法): 运行阶段的时候,实际上在堆内存中创建的Java对象是Dog对象和Bird对象,
* 所以move的时候,真正参与move的对象是一只狗和一只鸟,所以运行阶段会 动态执行Dog对象和Bird对象的move()方法,此过程属于动态绑定
*/
animal2.move(); // Dog run...
animal3.move(); // Bird fly...
// 调用或者执行子类对象中特有的方法
/*
* animal2.sing(); 编译报错,Animal.class字节码文件中无法找到sing()方法,谈不上运行 The method sing()
* is undefined for the type Animal
*/
// animal2.sing();
// animal3.run();
// 通过向下转型解决animal2.sing();与animal3.run();
// animal2、animal3是Animal类型,Dog、Bird与Animal之间存在继承关系
System.out.println("================");
Dog d1 = (Dog) animal2;
Bird b1 = (Bird) animal3;
d1.run(); // Dog run...
b1.sing(); // Bird sing...
// 向下转型的风险
Animal animal4 = new Dog();
Dog d2 = (Dog) animal4;
/*
* 编译不报错,编译器检测到animal4是Animal类型,而Animal与Dog之间存在继承关系,所以可以向下转型
* 运行阶段,堆内存实际上创建的是Dog对象,但Dog和Bird之间没有继承关系
* java.lang.ClassCastException(类型转换异常)
*/
//d2.sing();
// 如何避免向下转型的风险,避免ClassCastException
/*
* 向下转型之前使用 instanceof 运算符进行判断,以此来确定某个引用指向的对象是否为某一种类型
*/
if(animal4 instanceof Dog) {
Dog d2 = (Dog) animal4;
d2.sing();
}
}
}
本文地址:https://blog.csdn.net/LvJzzZ/article/details/107369949
推荐阅读