多态基础

关于多态中涉及到的几个概念:

向上转型(upcasting)

子类型 --> 父类型

又被称为:自动类型转换。

向下转型(downcasting)

父类型 --> 子类型

又被称为:强制类型转换。「需要加强制类型转换符」

无论是向上转型还是向下转型,两种类型之间必须要有继承关系,没有继承关系,程序是无法编译通过的。

多态语法机制

Animal和Cat之间存在继承关系,Animal是父类,Cat是子类

Cat is an Animal.

new Cat()创建的对象的类型是Cat,cat这个引用的数据类型是Animal,可见他们进行了类型转换。子类型转成父类型,称为向上转型

Java支持父类型引用指向子类型对象。

Animal a2 = new Cat();

public class Cat extends Animal {

@Override

public void move(){

System.out.println("猫在地上走!");

}

}

public class Animal {

public void move(){

System.out.println("动物在飞行!");

}

}

Java程序永远都分为编译阶段和运行阶段。

先分析编译阶段,再分析运行阶段,编译无法通过,程序是无法运行的。

编译阶段编译期检查cat这个引用的数据类型为Animal,由于Animal.class字节码文件中有move()方法,所以编译通过了。这个过程我们称为静态绑定,编译阶段绑定。只有静态绑定成功后才有后续的运行。

在程序运行阶段,JVM堆内存当中真实存在的对象是Cat对象,那么以下程序在运行阶段一定会调用Cat对象的move()方法,此时发生了程序的动态绑定,运行阶段绑定。

无论Cat类有没有重写move方法,运行阶段调用的是Cat对象的move方法,因为底层真实对象是Cat对象

父类型引用指向子类型对象这种机制导致程序在编译阶段绑定和运行阶段绑定两种不同的状态、形态,这种机制可以成为一种多态语法机制。

输出结果猫在地上走!

a2.move();

假设Cat里有一个catchMouse方法,以下程序为什么不能调用?

因为编译阶段编译器检查到a2的类型是Animal类型,从Animal.class字节码文件中查找catchMouse()方法,最终没有找到该方法,导致静态绑定失败,没有绑定成功,也就是说编译失败了。

a2.carchMouse();

若想要调用catchMouse()方法,怎么办?

a2是无法直接调用的,因为a2的类型是Animal,Animal中没有catchMouse()方法。我们可以将a2强制类型转换为Cat类型

a2类型是Animal(父类),转换成Cat类型(子类),被称为向下转型/downcasting/强制类型转换。

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

当调用的方法是子类型中特有的,在父类型中不存在。必须向下转型。

向下转型也需要两种类型之间必须有继承关系。不然编译报错。强制类型转换需要加强制类型转换符。

((Cat)a2).catchMouse();

Animal a2 = new Cat();内存图

public class Bird extends Animal{

public void move(){

System.out.println("小鸟在天上飞!");

}

}

Animal a3 = new Bird();

以下程序会不会报错?为什么??

以下程序编译时没有问题的,因为编译器检查到a3的数据类型是Animal,Animal和Cat之间存在继承关系,并且Animal是父类型,Cat是子类型,父类型转换子类型叫做向下转型,语法通过。

程序在运行阶段出现异常,因为JVM堆内存中真实存在的对象是Bird类型,Bird对象无法转换成Cat对象,因为两种类型之间不存在任何继承关系,此时出现著名的异常:

java.lang.ClassCastException

类型转换异常,这种异常总是在向下转型的时候发生。

Cat c3 = (Cat)a3;

以上异常只有在强制类型转换的时候会发生,也就是说“向下转型”存在安全隐患(编译过了,但运行错了!)

向上转型只要编译过了,运行一定不会出问题。Animal a2 = new Cat();

向下转型编译通过,运行可能发生错误

Animal a3 = new Bird();

Cat c3 = (Cat)a3;

怎么避免向下转型出现的异常ClassCastExcption?

使用instanceof运算符可以避免出现以上的异常。

instanceof

语法

(引用 instanceof 数据类型名称)

instanceof运算符的执行结果是布尔类型,结果是true/false

关于运算结果true/false

假设(a instanceof Animal)

true表示a这个引用指向的对象是一个Animal类型

false表示a这个引用指向的对象不是一个Animal类型

Java规范中要求:在进行强制类型转换之前,建议采用instanceof运算符进行判断,避免ClassCastException异常的发生

instanceof运算符

public class Cat extends Animal {

@Override

public void move(){

System.out.println("猫在地上走!");

}

public void catchMouse(){

System.out.println("我开始抓老鼠了!");

}

}

使用instanceof

Animal cat = new Cat();

if (cat instanceof Bird)

((Bird)cat).move();

else if (cat instanceof Cat)

((Cat)cat).catchMouse();

输出我开始抓老鼠了!

Animal cat = new Bird();

if (cat instanceof Bird)

((Bird)cat).move();

else if (cat instanceof Cat)

((Cat)cat).catchMouse();

输出小鸟在天上飞!

多态的作用

多态在实际开发中的作用,以下以主人喂养宠物为例说明多态:

主人喂养宠物这个场景要实现需要进行的抽象:

主人「类」

主人可以喂养宠物,所以主人有喂养的这个动作

宠物「类」

宠物可以吃东西,所以宠物有吃东西这个动作

定义好类,后将类实例化为对象,给一个环境驱使一下,让各个对象之间协作起来形成一个系统。

多态的作用是什么?

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

能使用多态尽量使用多态

父类型引用向子类型对象。

面向抽象编程,尽量不要面向具体编程

创建类:

//主人类

public class Hoster{

public void fedd(Cat cat){

cat.eat();

}

}

//猫类

public class Cat {

public void eat(){

System.out.printf("猫在吃小鱼干!\n");

}

}

实例

Hoster hoster = new Hoster();

Cat tom = new Cat();

tom.petName = "tom";

hoster.fedd(tom);

运行输出:

tom在吃小鱼干!

如果主人想养狗,那么以上程序不使用多态需要这样改动:

public class Hoster{

public void fedd(Cat cat){

cat.eat();

}

public String petName;

public void fedd(Dog dog){

dog.eat();

}

}

//狗类

public class Dog {

String catType;

public void eat(){

System.out.printf("狗在吃骨头!\n");

}

}

以上程序因为耦合度太高,无法灵活拓展。如果需要程序拓展能力强,需要降低程序的耦合度「解耦合」,提高扩展能力

使用多态

添加一个宠物类,将所有宠物都继承这个宠物类。

public class HousePet{

public void eat(){

System.out.printf("主人不给东西吃!\n");

}

}

// 将所有宠物类继承宠物类

public class Dog extends HousePet{...}

public class Cat extends HousePet{...}

主人类使用多态

Hoster主人类面向的是一个抽象的HousePet,不再是具体的宠物.

public class Hoster{

public void fedd(HousePet HP){

HP.eat();

}

}

使用时只需要将继承了HousePet的宠物传给Hoster下的fedd方法

Hoster hoster = new Hoster();

hoster.fedd(new Cat());

hoster.fedd(new Dog());

输出:

猫在吃小鱼干!

狗在吃骨头!

本文由 UpYou 创作,采用 知识共享署名4.0

国际许可协议进行许可

本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名

最后编辑时间为: 十一月 9,2020

java多态工作机制_Java多态相关推荐

  1. java多态的实现_Java多态的实现机制是什么,写得非常好!

    作者:crane_practice www.cnblogs.com/crane-practice/p/3671074.html 2019-06-13 08:46:00 Java多态的实现机制是父类或接 ...

  2. JavaWeb技术内幕二:Java IO工作机制

    IO问题是当今web应用所面临的主要问题之一,因为数据在网络中随处流动,在这个流动过程中都涉及IO问题,并且大部分应用的瓶颈都是IO瓶颈. 本章将从IO的角度出发,介绍IO类库的基本架构,磁盘IO的工 ...

  3. java io工作机制_深入分析Java I/O 工作机制

    前言 :  I/O 问题是Web 应用中所面临的主要问题之一.而且是任何编程语言都无法回避的问题,是整个人机交互的核心. java 的I/O类操作在java.io 包下,将近80个子类, 大概可以分成 ...

  4. java虚拟机工作原理_Java虚拟机工作原理具体解释

    一.类载入器 首先来看一下java程序的运行过程. 从这个框图非常easy大体上了解java程序工作原理.首先,你写好java代码,保存到硬盘其中.然后你在命令行中输入 javac YourClass ...

  5. java虚拟机工作原理_Java虚拟机工作原理详解

    一.类加载器 首先来看一下java程序的执行过程. 从这个框图很容易大体上了解java程序工作原理.首先,你写好java代码,保存到硬盘当中.然后你在命令行中输入: javac YourClassNa ...

  6. java的多线程机制_Java多线程开发(一)| 基本的线程机制

    0. 前言 Java 为了实现跨平台,在语言层面上实现了多线程.我们只需要熟悉 Java 这一套多线程机制就行了,比 C/C++ 要容易多了. 1. 定义任务 我们编写程序,最终是为了完成特定的任务. ...

  7. 说一下java的运行机制_Java运行机制是什么?

    不管是学习Java还是其他什么变成语言,我们不仅要了解它的特性,充分的使用Java语言完成各种程序开发工作,还要了解Java的运行机制.只有了解其底层的运行机制,才能更好的利用Java完成各项工作.J ...

  8. java程序并行机制_Java语言具有多种优点和特点,下列选项中,______反映了Java程序并行执行机制的特点。A.多线程B.健...

    Java语言具有多种优点和特点,下列选项中,______反映了Java程序并行执行机制的特点.A.多线程B.健 更多相关问题 根据句意及首字母完成单词1. -What c__________ is i ...

  9. java方法调用机制_Java方法调用机制 - osc_bkdv2it5的个人空间 - OSCHINA - 中文开源技术交流社区...

    最近在编程时,修改方法传入对象的对象引用,并没有将修改反映到调用方法中.奇怪为什么结果没有变化,原因是遗忘了Java对象引用和内存分配机制.本文介绍3个点: ① 该问题举例说明 ② 简要阐述Java内 ...

最新文章

  1. 2017 ACM/ICPC 南宁赛区小结 By JSB @ Reconquista
  2. 创建一个简单的存储过程(RroGetA_Z),要求输出A到Z之间的26个大写字母
  3. tnsname.ora文件配置详解
  4. ldap添加自定义字段
  5. lwip1.4.1需要的文件
  6. ORACLE SQL:经典查询练手第三篇
  7. 构建和运行Java 8支持
  8. Facebook哭晕在厕所,调查显示用VR体验社交的用户仅为19%
  9. Eclipse之ANT使用
  10. MVC初学 - The type or namespace name 'DbContext' could not be found
  11. linux 开机启动项管理
  12. RedHat Linux下获取snmp信息不全的解决办法
  13. S3C2440 进行微秒级、毫秒级延时函数
  14. 360浏览器升级_社畜必备!360浏览器上线“文档”功能 一键开启云办公
  15. 网络工程师的python之路pdf下载_网络工程师的Python之路:网络运维自动化实战
  16. Java通俗易懂30天 第1天: Java语言概述
  17. 三大运营商流量卡的现状:不兼容,死卡,三网物联卡你选对了吗?
  18. 2012服务器系统显示这台电脑,两台windows server 2012 R2 服务器 故障:计算机已经从检测错误后重新启动。请问如何解决?...
  19. 2022.11.05 第六次周报
  20. 现在40系显卡都快出来了,为何1060型号的显卡还有这么多人用?

热门文章

  1. 逐飞K66核心板+逐飞DAP下载器调试方式及接线(SWD)
  2. 华为什么型号支持鸿蒙,哪些华为手机支持鸿蒙系统?华为支持鸿蒙OS手机型号清单...
  3. 1000道最新大厂高频Java面试题,覆盖25个技术栈(多线程、JVM、高并发、spring、微服务、kafka,redis、分布式)从底层原理到架构
  4. Python数据分析基础技术之scikit-learn(史上最全面)
  5. 云计算未来 — 云原生
  6. SpringBoot安全验证之Referer拦截器
  7. 镁光闪存颗粒对照表_详解闪存颗粒的种类
  8. Codeforces Round #727 (Div. 2)题解A-D
  9. 买入高价显卡的回血方法
  10. 【逻辑训练】来自可汗学院的有趣逻辑问题