深度分析:理解Java中的多态机制,一篇直接帮你掌握!
Java中的多态
1 多态是什么
多态(Polymorphism)按字面的意思就是“多种状态”。在面向对象语言中,接口的多种不同的实现方式即为多态。用白话来说,就是多个对象调用同一个方法,得到不同的结果。
2 多态的语法格式
父类类名 引用名称 = new 子类类名();
当是多态时,该引用名称只能访问父类中的属性和方法,但是访问的时候,会优先访问子类重写以后的方法。
3 满足多态的条件
子类必须继承父类
子类必须重写父类的方法
父类引用指向子类对象,即:父类类名 引用名称 = new 子类类名();
4 使用多态好处
使用多态可以使代码之间的耦合度降低
减少冗余代码的同时,也使得项目的扩展能力更强
注:耦合度指的是代码(程序)之间的关联程度
5 多态中的类型转换
Java多态中,有两种类型转换:向上转型和向下转型
向上转型
向上转型,也叫做自动类型转换,子类型赋值给父类型(父类型的引用指向子类型),构成多态
父类类型 引用名称 = new 子类类名();
当使用多态方式调用方法时,该引用名称只能访问父类中的属性和方法。编译器首先检查父类中是否有该方法,如果没有,则编译错误。如果有,再去调用子类的同名(重写)方法。
向下转型
向下转型,也叫做强制类型转换,父类型赋值给子类型
当使用多态时,并且访问子类独有的属性或方法时,则必须进行向下转型
当进行向下转型时,建议先使用 instance of 关键字进行判断,判断合法时,则在转为对应的类型,否则可能会出现类型转换异常 java.lang.ClassCastException。
说明:instance of 关键字用于判断一个对象,是否属于某个指定的类或其子类的实例。
6 多态的实现方式
普通子类重写父类方法
接口
生活中的接口最具代表性的就是插座,例如一个三接头的插头都能接在三孔插座中,因为这个是每个国家都有各自规定的接口规则,有可能到国外就不行,那是因为国外自己定义的接口类型。
USB接口也很典型,有了这个,使得接口统一,生活更加方便
抽象类和抽象方法
7 多态简单使用案例
场景:假如有个饲养员,需要给不同的宠物喂食,下面给出使用多态和不使用多态的实现方式。
不使用多态的实现:
首先定义一个抽象类Animal、一个饲养员类AnimalKeeper、一个宠物类Dog和一个宠物类Cat。
public abstract class Animal {
public void eat() {
System.out.println("动物吃东西!");
}
}
/**
* 饲养员
*/
public class AnimalKeeper { /**
* 给宠物猫喂食
*
* @param cat
*/
public void feed(Cat cat) {
cat.eat();
} /**
* 给宠物狗喂食
*
* @param dog
*/
public void feed(Dog dog) {
dog.eat();
} }
public class Dog extends Animal {
@Override
public void eat() {
System.out.println("狗啃骨头!");
}
}
public class Cat extends Animal {
@Override
public void eat() {
System.out.println("猫吃鱼!");
}
}
测试类:
public class PolymorphicTest {
public static void main(String[] args) {
//创建饲养员对象
AnimalKeeper animalKeeper = new AnimalKeeper();
//创建宠物对象
Cat cat = new Cat();
animalKeeper.feed(cat);//猫吃鱼!
Dog dog = new Dog();
animalKeeper.feed(dog);//狗啃骨头!
}
}
以上实现看起来没有什么问题,也容易理解,在目前情况下,饲养员可以满足喂养宠物的需求。但是,过了一周,饲养员又喂养了一只鸟,这时候不得不修改AnimalKeeper类,使其可以饲养宠物鸟,不仅违反了Java中的开闭原则,而且以上代码的实现,扩展性极差。
使用多态的实现:
只需要对以上代码中,饲养员类AnimalKeeper进行替换,新增一个饲养员类AnimalKeeperPolymorphic类。
/**
* 饲养员
*/
public class AnimalKeeperPolymorphic { /**
* 饲养员给宠物喂食
*
* @param animal
*/
public void feed(Animal animal) {
animal.eat();
} }
测试用例:
public static void change() {
//创建饲养员对象
AnimalKeeperPolymorphic animalKeeper = new AnimalKeeperPolymorphic();
//创建宠物对象
Cat cat = new Cat();
animalKeeper.feed(cat);//猫吃鱼!
Dog dog = new Dog();
animalKeeper.feed(dog);//狗啃骨头!
}
这种实现有什么好处呢,当新需求来了,需要扩展时,不需要修改饲养员的代码。比如说刚才那个需求,新增加一个宠物鸟,只需要新建一个宠物鸟类,实现Animal接口,不仅遵循了OCP原则,也可以实现饲养宠物鸟的功能。
8 多态分析
以上文中示例代码进行分析,看看多态是如何使用的。
AnimalKeeperPolymorphic中的feed()方法,使用了多态。
当饲养员喂养宠物狗时,其实执行的是:
Animal animal = new Dog();
当饲养员喂养宠物猫时,其实执行的是:
Animal animal = new Cat();
这种属于向上转型,里面有继承(cat继承Animal)关系,重写了父类eat()方法,子类型赋值给父类型(父类型的引用指向子类型),构成了多态。
Animal animal = new Cat(); 程序在编译阶段,animal引用类型被编译器看做Animal类型,所以程序在编译阶段,animal引用绑定的是Aninmal类中的eat()方法,这个过程叫做Java多态的静态绑定。
程序在运行的时候,堆中的对象实际上是Cat类型,而Cat对象已经覆盖(重写)了父类Animal的eat()方法,所以程序在运行阶段,对象绑定的方法是Cat中的eat()方法,这个过程叫做Java多态的动态绑定。
写博客是为了记住自己容易忘记的东西,另外也是对自己工作的总结,希望尽自己的努力,做到更好,大家一起努力进步!
如果有什么问题,欢迎大家一起探讨,代码如有问题,欢迎各位大神指正!
给自己的梦想添加一双翅膀,让它可以在天空中自由自在的飞翔!
深度分析:理解Java中的多态机制,一篇直接帮你掌握!的更多相关文章
- 【Java】深入理解Java中的spi机制
深入理解Java中的spi机制 SPI全名为Service Provider Interface是JDK内置的一种服务提供发现机制,是Java提供的一套用来被第三方实现或者扩展的API,它可以用来启用 ...
- 深入理解Java中的多态
一.什么是多态? 多态指同一个实体同时具有多种形式.它是面向对象程序设计(OOP)的一个重要特征.如果一个语言只支持类而不支持多态,只能说明它是基于对象的,而不是面向对象的. 二.多态是如何实现的? ...
- 由ArrayList来深入理解Java中的fail-fast机制
1. fail-fast简介“快速失败”也就是fail-fast,它是Java集合的一种错误检测机制.某个线程在对collection进行迭代时,不允许其他线程对该collection进行结构上的修改 ...
- 夯实Java基础系列11:深入理解Java中的回调机制
目录 模块间的调用 多线程中的"回调" Java回调机制实战 实例一 : 同步调用 实例二:由浅入深 实例三:Tom做题 参考文章 微信公众号 Java技术江湖 个人公众号:黄小斜 ...
- 深度分析:Java中如何如理异常,一篇帮你搞定!
异常的背景 初识异常 我们曾经的代码中已经接触了一些 "异常" 了. 例如: 除以 0 System.out.println(10 / 0); // 执行结果 Exception ...
- 深入理解Java中的反射机制
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意方法和属性:这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制. ...
- 夯实Java基础系列12:深入理解Java中的反射机制
本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutorial 喜欢的话麻烦点下 ...
- 深入理解Java中的反射机制和使用原理!详细解析invoke方法的执行和使用
反射的概念 反射: Refelection,反射是Java的特征之一,允许运行中的Java程序获取自身信息,并可以操作类或者对象的内部属性 通过反射,可以在运行时获得程序或者程序中的每一个类型的成员活 ...
- JDK学习---深入理解java中的HashMap、HashSet底层实现
本文参考资料: 1.<大话数据结构> 2.http://www.cnblogs.com/dassmeta/p/5338955.html 3.http://www.cnblogs.com/d ...
随机推荐
- Unity控制角色移动
Copy代码前的准备工作 整体结构 建立个空对象命名随意,主要是为了:角色掉出地图时,可以回到空对象的位置 在建立个空对象命名为Player,放到PlayResurrectionPoints子级下,并 ...
- APP打开(三)—激活率提升20%的思考
激活是APP拉新后的一个重要环节.通常,我们希望用户打开我们的APP之后,能够顺利的被激活,从而留下来成为我们的忠实用户. 激活一词,就跟北斗星指标一样,对每个产品来说都是不一样的.有些APP一旦打开 ...
- 结对项目的PS表格
PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟) Planning 计划 60 80 Estimate 估计这个任务需要多少时间 10 ...
- (CS229)监督学习应用和梯度下降
监督学习:基于标记数据的学习 监督学习又举了两个例子:回归问题regression在连续数据上的模型构建问题 和 分类问题 classification 在离散数据上的问题 无监督学习:未标记的学习 ...
- 常用命令--windows
查看端口号是否占用并杀进程 1 netstat -ano | findstr " " 2 tasklist | findstr " " 3 taskkill / ...
- glog修改
在写代码的过程中,打log肯定是少不了的,毕竟不能总靠调试来发现问题.log库的选用就很纠结了,成熟的log库非常多,log4cpp.log4cxx.poco.log.boost.log.glog等等 ...
- P2966 [USACO09DEC]Cow Toll Paths G
题意描述 Cow Toll Paths G 这道题翻译的是真的不错,特别是第一句话 给定一张有 \(n\) 个点 \(m\) 条边的无向图,每条边有边权,每个点有点权. 两点之间的路径长度为所有边权 ...
- 框架篇:见识一下linux高性能网络IO+Reactor模型
前言 网络I/O,可以理解为网络上的数据流.通常我们会基于socket与远端建立一条TCP或者UDP通道,然后进行读写.单个socket时,使用一个线程即可高效处理:然而如果是10K个socket连接 ...
- 巧用IDM工具 快捷下载ASTER GDEM v3高程数据
ASTER GDEM v3是NASA推出的30米高清DEM,覆盖了几乎全部的地球陆地.那么,在NASA官网怎么下载ASTER GDEM v3的地形高程数据呢? 首先,你需要注册一个nasa的账号 注册 ...
- 安装tomcat for ubuntu linux差点没晕死我!
我滴个神!装ubuntu的tomcat差点没有晕死我!怎么回事呢? 应该说是装好了,执行了bin/startup.sh了,出现以下画面: Using CATALINA_BASE: /home/niew ...