ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

java基础_多态(转载)

2022-06-21 09:34:08  阅读:162  来源: 互联网

标签:java 子类 move 多态 Cat 编译 Animal 转载 class


(转载自https://blog.csdn.net/hu4545/article/details/125054634

什么是多态?

多种形态,多种状态。具体指:编译的时候一种形态,运行的时候另一种形态。
指的是父类型的引用指向子类型的对象。编译阶段:静态绑定父类的方法;运行阶段:动态绑定子类型对象的方法。

学习多态前需要了解两个基本概念:向上转型(子转父)、向下转型(父转子)。
注意: 在java语法中既允许向上转型,也允许向下转型。但无论是向上转型还是向下转型都必须要有继承关系,两者之间没有继承关系,编译报错(这句话不适用于接口之间)。

什么时候需要用到向下转型?

不要随便进行类型转换,当你所需要访问的方法是子类特有的,此时必须使用向下转型!

案例代码

父类:Animal.class

// 动物类:父类
public class Animal{
	// 移动的方法
	public void move(){
		System.out.println("动物在移动!");
	}
}

子类:Cat.class

// 猫类,子类
public class Cat extends Animal{
	// 对move方法进行重写
	public void move(){
		System.out.println("cat走猫步!");
	}
	// 猫除了move之外,应该有自己特有的行为,例如抓老鼠。
	// 这个行为是子类型对象特有的方法。
	public void catchMouse(){
		System.out.println("猫正在抓老鼠!");
	}
}

子类:Brid.class

// 鸟类,子类
public class Brid extends Animal{
	// 对move方法进行重写
	public void move(){
		System.out.println("Brid在飞翔!");
	}
}

测试类:Test.class

public class Test{
	public static void main(String[] args){
		Animal a1 = new Cat(); //父类型的引用指向了子类型的对象
		a1.move();   //输出结果:cat走猫步!

	//===注意:a1与a2两个实例是分开测试的,a1可以编译通过===
		Animal a2 = new Cat(); //父类型的引用指向了子类型的对象
		a2.catchMouse();   //编译报错,找不到符号
	}
}

输出结果分析:

一、a1.move() 为什么输出结果为:cat走猫步! 而不是 动物在移动!

java程序分为编译阶段和运行阶段。
先来分析编译阶段:
对于编译器来说,编译器只知道a1的类型是Animal,所以编译器在检查语法的时候,会去Animal.class字节码文件中找move()方法,找到了,绑定上move()方法,编译通过,静态绑定成功。(编译阶段属于静态绑定。)
再来分析运行阶段:
运行阶段的时候,实际上在堆内存中创建的java对象是Cat对象,所以move的时候,真正参与move的对象是一只猫,所以运行阶段会动态执行Cat对象的move()方法。这个过程属于运行阶段绑定。(运行阶段绑定属于动态绑定。)
编译的时候一种形态,运行的时候另一种形态。这就是多态。

二、a2.catchMouse() 为什么编译报错?

对于编译器来说,编译器只知道a2的类型是Animal,所以编译器在检查语法的时候,会去Animal.class字节码文件中找catchMouse()方法,结果没有找到,静态绑定失败,编译报错。

三、如何解决a2非要调用catchMouse()的编译报错问题?

这个时候必须要使用 向下转型。
a2是Animal类型,强制转换为了Cat类型,Animal与Cat之间存在继承关系,所以不会报错。这里是从 Animal–> Cat (父类到子类)向下转型。

Animal a2 = new Cat();
Cat cat = (Cat)a2;  // (Cat)是强制类型转换符
cat.catchMouse();  //输出结果:猫正在抓老鼠!

向下转型有风险吗?

//观察这段测试代码
Animal a3 = new Brid(); 
Cat cat = (Cat)a3; 
cat.catchMouse(); //java.lang.ClassCastException:类型转换异常。

编译通过运行报错,java.lang.ClassCastException:类型转换异常。
编译阶段:编译器检测a3是Animal类型,而Animal与Cat存在继承关系,所以可以向下转型,编译通过。运行阶段:堆内存实际创建的对象是:Brid对象,在实际运行的过程中,拿着Brid对象转换成Cat对象就不行了,应为Brid和Cat之间不存在继承关系。

怎么避免ClassCastException异常发生?

通过 instanceof 关键字,可以动态判断引用指向的对象的类型。
在java规范中,对类型进行向下转型时,一定要使用 instanceof 运算符进行判断。

Animal a3 = new Brid(); 
System.out.println(a3 instanceof  Cat);  // false
if(a3 instanceof  Cat){  //如果a3是一只猫
  Cat cat = (Cat)a3; 
  cat.catchMouse();   //编译通过、运行通过,因为压根不执行
}

instanceof 语法:
语法格式: 引用 instanceof 类型
instanceof 运算符的运算结果只能是 true / false

案例:c是一个引用,c变量保存了内存地址指向了堆内存中的对象。
假设 (c instanceof Cat)为true 表示:c引用指向的堆内存中的java对象是一个Cat。
假设 (c instanceof Cat)为false表示:c引用指向的堆内存中的java对象不是一个Cat。

实现多态的条件:

1、继承:必须要有子类继承父类的继承关系。
2、重写:子类需要对父类中的一些方法进行重写,然后调用方法时就会调用子类重写的方法而不是原本父类的方法。
3、向上转型:在多态中需要将子类的引用赋给父类对象,只有这样该引用才能够具备技能调用父类的方法和子类的方法。

多态的作用:

降低程序的耦合度,提高程序的扩展力。
使程序符合OCP(开闭)原则,对扩展开放,对修改关闭。

标签:java,子类,move,多态,Cat,编译,Animal,转载,class
来源: https://www.cnblogs.com/succodes/p/16395690.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有