IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> Java——多态 -> 正文阅读

[Java知识库]Java——多态

多态

一、向上转型与向下转型

(一)向上转型
//动物类,父类
public class Animal{
	//移动的方法
	public void move(){
		  System.out.println("动物在移动!");
	}
}
//猫类,子类
public class Cat extends Animal{
//对move()方法进行重写
	public void move(){
		  System.out.println("cat在走猫步");
	}
}
//鸟类,子类
public class Bird extends Animal{
//对move()方法进行重写
	public void move(){
		  System.out.println("鸟儿在飞翔");
	}
}
//测试类
public class Test{
	 public static void main(String[] args) {
       Animal a1 = new Animal();
       a1.move();	//	动物在移动!
       
       Cat a2 = new Cat();
       a2.move();	//	cat在走猫步
       
       Bird a3 = new Bird();
       a3.move();	//	鸟儿在飞翔
    }
}

以上代码正常执行,并且正常运行出结果。现在试试测试类能不能这么写?

public class Test{
	 public static void main(String[] args) {
       Animal a1 = new Animal();
       a1.move();	//	动物在移动!
       
       Animal a2 = new Cat();
       a2.move();	//	cat在走猫步
       
       Animal a3 = new Bird();
       a3.move();	//	鸟儿在飞翔
    }
}

Animal a2 = new Cat();

a2就是父类型的引用

new Cat()是一个子类型的对象。

允许a2这个父类型引用指向子类型的对象。

这个语法被称为向上转型


学习多态基础语法之前,先学习两个概念:

第一个:向上转型

? 子------->父(自动类型转换)

第二个:向下转型

? 父-------->子(强制类型转换,需要加强制类型转换符)

注意:无论向上转型还是向下转型,两种类型之间必须有继承关系,没有继承关系编译器会报错。

java程序分为编译阶段和运行阶段。

编译阶段:

? 对于编译器来说,编译器只知道a2的类型是Animal,所以编译器在检查语法的时候,会去Animal.class字节码文件

? 中找move()方法,找到后绑定上move()方法,编译通过,静态绑定成功。(编译阶段属于静态绑定。)

运行阶段:

? 运行阶段的时候,实际上在堆内存中创建的java对象是Cat对象,所以move的时候,真正参与move的对象是一只猫,

? 所以运行阶段会动态执行Cat对象的move()方法。这个过程属于运行阶段绑定。(运行阶段绑定属于动态)

多态表示多种形态:

? 编译的时候一种形态。

? 运行的时候另一种形态。

多态指的是:

? 父类型引用指向子类型对象。包括编译阶段和运行阶段。

? 编译阶段:绑定父类的方法。

? 运行阶段:动态绑定子类型对象的方法。


(一)向下转型

不要随便做强制类型转换,当你需要访问的是子类对象中“特有”的方法,此时必须进行向下转型。

假设将以上代码中Cat类改为:

//猫类,子类
public class Cat extends Animal{
//对move()方法进行重写
	public void move(){
		  System.out.println("cat在走猫步");
	}
	public void catchMouse(){
		  System.out.println("猫正在抓老鼠!");
	}
}

测试类调用

public class Test{
	 public static void main(String[] args) {
       Animal a1 = new Animal();
       a1.move();	//	动物在移动!
       
       Animal a2 = new Cat();
       a2.move();	//	cat在走猫步
       
       Animal a3 = new Bird();
       a3.move();	//	鸟儿在飞翔
       
       Animal a4 = new Cat();//a4是Animal类型,转成Cat
       Cat x = (Cat)a4;
       x.catchMouse();	//	猫正在抓老鼠!
    }
}

这里就是向下转型。

向下转型有风险吗?分析以下程序:

public class Test{
	 public static void main(String[] args) {
       Animal a1 = new Animal();
       a1.move();	//	动物在移动!
       
       Animal a2 = new Cat();
       a2.move();	//	cat在走猫步
       
       Animal a3 = new Bird();
       a3.move();	//	鸟儿在飞翔
       
       Animal a4 = new Cat();//a4是Animal类型,转成Cat
       Cat x = (Cat)a4;
       x.catchMouse();	//	猫正在抓老鼠!
       
       Animal a5 = new Bird();
       Cat y = (Cat)a5;
       y.catchMouse();
    }
}

在编译阶段,编译器检测到a5这个是Animal类型,而Animal与Cat之间也存在继承关系,所以向下转型编译上没有问题。

在运行阶段,堆内存实际创建的对象是:Bird对象。在实际运行过程中,拿着Bird对象转换成Cat对象就不行,因为它们

之间不存在继承关系。

会出现java.lang.ClassCastException:类型转换异常。

那么如何去避免ClassCastException异常的发生呢?

引入运算符instanceof

第一:instanceof可以再运行阶段动态判断引用指向的对象的类型。

第二:instanceof的语法

? (引用 instanceof 类型)

第三:insatanceof运算符的结果只能是:true 或者false。

第四:c是一个引用,c变量保存了内存地址指向了堆中的对象。

? 假设(c instanceof Cat)为true表示:

? c引用指向的堆内存中的java对象是一个Cat。

? 假设(c instanceof Cat)为false表示:

? c引用指向的堆内存中的java对象是一个Cat。

程序员应该养成一个习惯,对类型进行向下转型时,一定要用instanceof运算符进行判断!!

所以将以上程序改为:

public class Test{
	 public static void main(String[] args) {
       Animal a1 = new Animal();
       a1.move();	//	动物在移动!
       
       Animal a2 = new Cat();
       a2.move();	//	cat在走猫步
       
       Animal a3 = new Bird();
       a3.move();	//	鸟儿在飞翔
       
       Animal a4 = new Cat();//a4是Animal类型,转成Cat
       Cat x = (Cat)a4;
       x.catchMouse();	//	猫正在抓老鼠!
       
       Animal a5 = new Bird();
       if(a5 instanceof Cat){
       Cat y = (Cat)a5;
       y.catchMouse();
       }
    }
}

多态在开发中的作用

有以下练习题:

编写程序模拟“主人”喂养“宠物”的场景

//宠物狗狗类
public class Dog{
	//提供一个吃的方法
	public void eat(){
	System.out.println("狗狗喜欢啃骨头,吃的很香!");
	}
}
//主人类
public class Master{
	//喂养宠物狗狗
	//这是最初开始的时候,主人只喜欢养Dog
	public void feed(Dog d){
	d.eat();
	}
}
public class Test{
	 public static void main(String[] args){
	 	//创建主人对象
	 	Master ding = new Master();
	 	//创建宠物对象
	 	Dog d = new Dog();
	 	//主人喂宠物
	 	ding.feed(d);
	 }
}

这时候主人随着时间推移,主人又喜欢养猫咪,这就表示在实际开发中又产生了新的需求。

不使用多态的情况下,我们只能在Master类中添加一个新的方法。先添加一个猫咪类,然后由于新的需求产生,我们不得不对Master类进行修改。

**这样写代码的问题:**软件在扩展过程中,代码修改的越少越好,修改的越多,系统的稳定性越差,未知的风险就越多。

软件开发中有一个开闭原则:OCP(开闭原则) 对扩展开放,对修改关闭。

现在用多态进行代码编写。

//宠物狗狗类
public class Dog extends Pet{
	//提供一个吃的方法
	public void eat(){
		System.out.println("狗狗喜欢啃骨头,吃的很香!");
	}
}
//主人类
public class Master{
	//喂养宠物狗狗
	//这是最初开始的时候,主人只喜欢养Dog
	public void feed(Pet pet){
		pet.eat();
	}
}
public class Test{
    public static void main(String[] args){
        //创建主人对象
        Master ding = new Master();
        //创建宠物对象
        Dog d = new Dog();
        //主人喂宠物
        ding.feed(d);
		//创建猫的对象
        Cat c = new Cat();
        ding.feed(c);

    }
}
public class Cat extends Pet{
	public void eat(){
		System.out.println("猫猫喜欢吃鱼,吃的很香!");
	}
}
//宠物父类
public class Pet{
	public void eat(){}
}

就算日后主人又喜欢新的别的宠物,也不需要再对Master类进行修改,只需要按照需求进行增加即可。

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2021-09-19 07:51:35  更:2021-09-19 07:52:27 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 17:02:34-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码