当前位置: 移动技术网 > IT编程>开发语言>Java > JavaSE第十三章 多态

JavaSE第十三章 多态

2020年07月17日  | 移动技术网IT编程  | 我要评论
Java自我学习路线一、多态的基础语法1. 什么是多态2. 向上转型2.1 什么是向上转型3. 向下转型3.1 什么是向下转型3.2 什么时候向下转型3.3 向下转型的风险3.3.1 instanceof二、多态的作用1. 作用2. 开闭原则3. 简述面向对象三大特征三、多态存在的三个必要条件四、多态的实现方式一、多态的基础语法1. 什么是多态多态是同一个行为具有多个不同表现形式或形态的能力,即父类型引用指向子类型对象,期间包括编译阶段和运行阶段,编译阶段绑定父类型的方法(静态绑定),运行阶段绑定子

一、多态的基础语法

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

  1. instanceof 可以在运行阶段动态判断引用指向的对象的类型
  2. instanceof 的语法
引用 instanceof 类型
  1. instanceof 运算符的结果只能是 true/false

二、多态的作用

1. 作用

  • 降低程序的耦合度,提高程序的扩展力

2. 开闭原则

  • OCP:对扩展开放,对修改关闭(目的:降低程序的耦合度,提高程序的扩展力)

3. 简述面向对象三大特征

  • 有了封装,对象与对象之间产生了继承,有了继承之后,才有了方法的重写和多态
  • 封装:安全性和重用性
  • 继承:高效性和重用性
  • 多态:统一性和高效性

三、多态存在的三个必要条件

  1. 继承
  2. 重写
  3. 父类引用指向子类对象

四、多态的实现方式

  1. 重载、重写
  2. 接口(接口定义方法,方法的实现在继承接口的具体类中定义)
  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

如您对本文有疑问或者有任何想说的,请 点击进行留言回复,万千网友为您解惑!

相关文章:

验证码:
移动技术网