Java多态(向上转型、动态绑定)+结合题目理解原理

news2024/11/24 0:00:09

第一次尝试使用markdowm写博客哈

文章目录

  • 1.多态的引入
  • 2.重写和重载
  • 3.避免在构造方法里面去调用重写
  • 4.向上转型和向下转型
  • 5.让你真正明白什么是多态
  • 6.通过一些习题进行理解

1.多态的引入

首先说一下,这个想要使用多态需要我们满足的条件,然后具体的进行阐述:

1.必须要在我们的继承的体系之下,就是这个多态是基于继承关系的;
2.子类需要对于父类的方法进行重写;
3.通过父类的引用调用重写的方法;

首先我们通过下面的这个代码,看一下什么是—向上转型:
这个是我们的代码里面的基类animal
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在我们的这个main方法里面,是定义了两个对象,一个是指向cat这个子类的引用,一个是指向dog这个子类的引用,这个new一个cat这个对象,这个时候,我们的cat这个子类赋值给了这个animal这个基类的对象,这个就是我们上面说的这个向上转型;

此外我们的这个向上转型可以通过参数的传递和方法的返回值实现:

参数的传递就是我们的func(父类对象),但是我们进行这个func函数调用的时候,使用的是这个func(子类)进行调用的,这个就是参数的传递引起的向上转型现象,这个我们传递的参数是子类的对象,但是这个方法里面使用的是父类的对象进行接收,这个时候就是向上转型;

方法的返回值就是func函数的返回值是一个父类的对象,但是我们的return的时候返回一个子类的对象,这个时候也是不会报错的,这个return子类对象到父类的过程就是向上转型;

2.重写和重载

其实这个学过C++的都知道这个函数的重载(因为我自己学过,所以更有体会),两个编程语言的这个机制都是相通的,我们的这个java里面的重载是方法重载,这个方法其实就是函数,这个里面的重载,其实和我们的函数重载没有太大的区别;

尤其是这个final这个关键字,它的作用和我们在C++里面学习的这个const更是如出一辙,就是相同的意思,我觉得就是想要换一个名字,彰显和别人的不同:

重写就是我们的这个方法的里面的参数,以及这个返回值都是要一样的

3.避免在构造方法里面去调用重写

就是这个构造方法里面加上我们的重写之后可能会出现很多的问题,下面的这个实例就是可能会出现的问题:

在这里插入图片描述
在这个里面,我们是写了一个B这个基类,我们D这个类是继承B的,因此我们的的这个主函数里面创建d这个对象的时候先回去调用父类的构造方法;

因为我们之前说过:执行顺序,父类的static方法,子类的static方法,父类的实例化,父类的构造,子类的实例化,子类的构造,因此在这个里面,我们没有静态的方法,因此这个就会从我们的父类的实例化和构造开始执行,这个时候父类里面没有实例化,因此这个时候直接执行我们的这个构造,这个时候的构造里面是一个func函数,这个函数在我们的父类和子类里面都是有实现的,但是这个时候在调用的时候我们调用的是子类的func函数,主要就是因为动态绑定(下面的一个点里面会说明):

运行的时候根据创建的对象的实际类型确定的,就是我们创建的是D类的对象,虽然这个func函数是在我们的B类里面的构造函数被调用的,但是因为我们创建的对象的类型,因此这个执行的时候执行的就是我们的D里面的func函数(和我们的创建对象的类型是一样的);

这个时候,我们执行子类里面的这个func函数,这个num打印的数值是我们的这个0而不是1,因为这个时候还没有进行这个num的初始化的工作,为什么呢,看下面的这个表:我们现在是执行的2这个步骤,这个时候我们是因为在额合格func函数跳转到了这个子类里面去,但是这个时候我们的执行顺序还是2这个步骤,当我们的3,4执行到子类的实例化和构造的时候,这个num才会被初始化,但是这个时候我们还是2这个阶段,因此这个num还是没有被初始化的,因此这个就是打印的结果就是0;

在这里插入图片描述
通过上面的这个例子,相信你也发现了,当我们的这个方法的重写和构造函数结合起来的时候,这个里面就会出现很多问题,因此我们不建议把两者结合起来使用,避免产生一些隐藏的让我们难以发现的问题;

4.向上转型和向下转型

我们上面的这个其实已经说明了什么是向上转型:例如我们的这个父类的引用指向的是我们的子类的对象,上面的这个animal animal1 = new cat()这样的写法,实际上就是这个animal这个父类的引用引用到的就是我们的子类的对象cat,这个从子类到父类,实际上就是向上转型的过程,前提是两个需要满足继承的关系,才可以进行转型;

向下转型就是和向上转型相反的,就是我们的基类被子类的对象引用所指向,这个时候需要进行强制类型转换,但是即使有些时候进行强制类型转换,也可能会出现一些问题,因为这个向下转型过程中出现的问题可能在编译阶段不会显示出来,在这个运行阶段会报错,这个也是常见的,下面的这个例子就是我们进行向下转型,强制类型转换的时候进行编译没有问题,但是运行之后就会出现问题:

在这里插入图片描述
这个截取的图片是没有运行的时候,编译器确实没有发现错误,但是给出了警告,实际上这个试运行无法通过的,就是因为我们的这个cat111向上转型成为这个animal1之后,我们的这个aniaml1的引用就是指向的我们的这个cat111这个对象,当我们强制类型转换的时候,这个是可以回来的;

但是,我们的这个aniaml1没有指向过这个dog111(这个主要是我们的cat111进行过向上转型,因此这个animal1的引用就是指向的我们的这个cat111这个对象,但是这份dog111没有向上转型),因此这个是无法通过我们的这个强制类型转换进行这个向下转型的操作的(这个错误编译器没有检查出来,但是确实无法运行通过);

5.让你真正明白什么是多态

上面也是说了很多,有的可能用处不大,但是都需要我们理解这些机制,下面的这个代码可以让我们直观清晰的感受到这个多态的现象,结合上面的语法进行这个现象的理解;

在这里插入图片描述
这个代码上面已经出现过,但是这个做了进一步的修改:我们定义了这个test函数在这个主方法里面,这个test函数的参数是我们的animal类的一个对象,就是父类的对象,但是我们传递参数的时候给的是子类的对象,这个时候从子类->父类的过程就是向上转型

在执行这个test方法的时候,我们的方法也不知道我们的传递参数具体是什么,但是当我们把这个animal这个对象传递过去的时候,这个时候打印的就是我们的这个小猫在吃鱼,当我们的这个animal传递过去的时候,这个时候打印的结果就是我们的小狗在吃骨头,像这样:相同的方法在调用的时候变现出来不一样的行为,这个现象就叫做多态

在这个代码里面,我们综合使用了向上转型,方法的重写,以及这个继承的相关的知识,也是用了这个super关键字对于这个子类里面的构造函数进行实现(有参数的话就需要我们自己去进行实现)

动态绑定:编译的时候,无法确定这个test函数的行为,因为这个具体我们会传递什么参数还是不确定的,但是这个并不影响,我们在运行的时候,就可以知道具体调用哪个类的方法(像上面的这个里面,我们传递animal1的时候,就具体的调用了我们的cat里面的这个方法,传递这个animal2的时候,就会具体调用dog里面的方法),在这个过程中,动态就是我们的这个调用的方法随着传递的参数是可以改变的,这个就是动态,绑定就是原来的这个编译的时候的不确定性到传递参数之后的这个具体调用的方法的确定性,这个调用的方法和调用的方法连接在了一起,这个就是绑定;

6.通过一些习题进行理解

下面的这个代码的输出结果:

这个主要考察的就是我们对于这个构造函数的理解,当我们的这个基类里面实现了我们的这个有参数的构造函数的时候,我们的这个子类就不会提供默认的构造函数,屙屎需要我们自己去写,这个里面,因为这个基类的构造函数是有一个String类型的参数的,因此这个时候我们需要在这个子类里面去实现这个super(s)从而实现对于我们的这个形参的初始化工作,否则就会报错;

class Base{
  public Base(String s){
    System.out.print("B");
  }
}

public class Derived extends Base{
  public Derived (String s) {
    System.out.print("D");
  }
  public static void main(String[] args){
    new Derived("C");
  }
}

下面的这个程序的执行结果:我们的执行顺序依然是这个父子类的静态方法,父类的实例化和构造,子类的实例化和构造方法;

这个里面没有静态的方法,因此这个时候直接进行实例化和构造的判断:这个主要就是捋清楚这个继承的层级关系,在这个里面,我们先到4这个地方,这个时候因为X是基类,因此会先去执行这个1这个地方,这个时候就会执行Y的构造函数,打印输出Y,然后我们就会到2这个位置,打印输出X,接着去执行子类的这个4这个位置(上面执行的都是父类的相关内容),主要就是因为想要执行子类的,首先就要执行父类的(执行父类的打印的结果是YX);

执行子类的时候,4打印结果Y,因为这个地方new了一个对象,然后执行5里面的内容,打印输出我们的Z;

class X{
	Y y=new Y();//1
	public X(){//2
		System.out.print("X");
	}
}
class Y{
	public Y(){//3
		System.out.print("Y");
	}
}
public class Z extends X{
	Y y=new Y();//4
	public Z(){//5
		System.out.print("Z");
	}
	public static void main(String[] args) {
		new Z();
	}
}

下面的这个代码的执行结果:

在下面的这个代码里面,我们的child是子类,main函数里面的这个子类的对象给了我们的父类的对象,这个就是向上转型的过程,但是因为这个p里面的成员变量是私有的,因此这个会出现编译报错的情况;

public class Person{

	private String name = "Person";

	int age=0;

}

public class Child extends Person{

	public String grade;

	public static void main(String[] args){

		Person p = new Child();

		System.out.println(p.name);

	}

}

下面的这个还是向上转型,我们的这个B是父类,所以new B的时候,这个里面的输出结果就是我们的B,但是我们new D的时候,因为这个里面的进行的是向上转型,但是这个是属于D的对象因此这个b进行func函数的调用的时候,就会调用这个D里面的func函数,打印输出D,这个就是动态绑定

class B {
    public int Func() {
        System.out.print("B");
        return 0;
    }
}
class D extends B {
    @Override
    public int Func() {
        System.out.print("D");
        return 0;
    }
}
public class Test {
    public static void main(String[] args) {
        B a = new B();
        B b = new D();
        a.Func();
        b.Func();
    }
}

好了,上面的几个题目,希望可以帮助你对于向上转型和动态绑定有更深层次的理解和体会~~~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2188453.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

进程概念(冯诺依曼体系结构、操作系统、进程)-- 详解

目录 一、冯诺依曼体系结构1、概念2、硬件层面的数据流3、关于冯诺依曼的知识点强调4、CPU 工作原理5、补充(CPU 和寄存器、高速缓存以及主存之间的关系) 二、操作系统(Operating System)1、概念2、定位3、设计 OS 的目的4、如何理…

Linux高级编程_28_进程

文章目录 进程并行与并发单道与多道程序进程控制块(PCB)了解PCB存储位置进程号:进程号:(PID)进程组号:(PGID)父进程号:(PPID) fork函数 多进程创建进程状态进…

基于vue框架的大学生勤工俭学咨询服务系统的设计与实现60uw9(程序+源码+数据库+调试部署+开发环境)系统界面在最后面。

系统程序文件列表 项目功能:大学生,企业,招聘信息,在线咨询,咨询回复,职位应聘 开题报告内容 基于Vue框架的大学生勤工俭学咨询服务系统的设计与实现 开题报告 一、研究背景 随着高等教育的普及与就业市场的竞争加剧,大学生勤工俭学已成为一种普遍现…

<<机器学习实战>>1-9节笔记

2.前言与导学 从关注算法的分类与特性到关注算法适合解决哪类问题 很多经典算法不再有效,但特征工程、集成学习越来越有效,和深度学习分别适合于不同领域 3、基本概念 如果预测目标是离散的,则是分类问题,否则回归 机器学习相比…

【AIGC】ChatGPT开发者必备:如何获取 OpenAI 的 API Key

博客主页: [小ᶻZ࿆] 本文专栏: AIGC | ChatGPT 文章目录 💯前言💯API Key的重要性💯获取API Key的基本步骤💯定价策略和使用建议💯小结 💯前言 在现代应用开发中,获取OpenAI的…

TCP Analysis Flags 之 TCP ZeroWindowProbe

前言 默认情况下,Wireshark 的 TCP 解析器会跟踪每个 TCP 会话的状态,并在检测到问题或潜在问题时提供额外的信息。在第一次打开捕获文件时,会对每个 TCP 数据包进行一次分析,数据包按照它们在数据包列表中出现的顺序进行处理。可…

什么是沉默成本?超详细+通俗易懂版

沉默成本是一个在会计学、金融学以及经济学中常用的概念,但更常见的表述是沉没成本(Sunk Cost)。沉没成本指的是已经发生且无法收回的成本,这些成本与当前的决策无关,但往往会影响人们的决策过程。以下是对沉没成本的详…

【MySQL】Ubuntu环境下MySQL的安装与卸载

目录 1.MYSQL的安装 2.MYSQL的卸载 1.MYSQL的安装 首先我们要看看我们环境里面有没有已经安装好的MySQL 我们发现是默认是没有的。 我们还可以通过下面这个命令来确认有没有mysql的安装包 首先我们得知道我们当前的系统版本是什么 lsb_release -a 我们在找apt源的时候&a…

vulnhub-unknowndevice64 2靶机

vulnhub:https://www.vulnhub.com/entry/unknowndevice64-2,297/ 导入靶机,放在kali同网段,扫描 靶机在192.168.81.9,扫描端口 啥啊这都是,详细扫描一下 5555是adb,6465是ssh,12345看样子应该是…

Python 工具库每日推荐 【BeautifulSoup】

文章目录 引言Python工具库的重要性今日推荐:BeautifulSoup工具库主要功能:使用场景:安装与配置快速上手示例代码代码解释实际应用案例获取 BeautifulSoup 官网文档首页的标题与所有图片案例分析扩展阅读与资源优缺点分析优点:缺点:总结【 已更新完 TypeScript 设计模式 专栏…

医疗应急三维电子沙盘系统

一、主要硬件功能指标要求: 1.沙盘尺寸≥98寸;分辨率:≥19201080;亮度500cd/m2;对比度4000:1;显示模式16:9;电源:100VAC~240VAC(50/60Hz)&#xf…

如何在 MySQL 中处理大量的 DELETE 操作

在 MySQL 数据库的使用过程中,我们有时会面临需要处理大量 DELETE 操作的情况。如果处理不当,可能会导致数据库性能下降、锁等待甚至系统崩溃。本文将介绍一些在 MySQL 中处理大量 DELETE 操作的方法。 一、问题背景 当需要删除大量数据时,…

手写mybatis之实现映射器的注册和使用

前言 其实对于解决这类复杂的项目问题,核心在于要将主干问题点缩小,具体的手段包括:分治、抽象和知识。运用设计模式和设计原则等相关知识,把问题空间合理切割为若干子问题,问题越小也就越容易理解和处理。就像你可以把…

【论文阅读】Segment Anything Model for Road Network Graph Extraction

【论文阅读】Segment Anything Model for Road Network Graph Extraction (CVPRW 2024) Paper链接:https://openaccess.thecvf.com/content/CVPR2024W/SG2RL/html/Hetang_Segment_Anything_Model_for_Road_Network_Graph_Extraction_CVPRW_2024_paper.html 文章目录…

基于SSM医疗信息管理系统(源码+定制+参考)

博主介绍: ✌我是阿龙,一名专注于Java技术领域的程序员,全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师,我在计算机毕业设计开发方面积累了丰富的经验。同时,我也是掘金、华为云、阿里云、InfoQ等平台…

vue文件的认识

1.package.json 项目包文件 里面包含许多可以在命令提示符中运行的命令,这里使用vue3创建的项目,所以dev是“vite”。 2.main.js 整个项目的入口文件,createApp创建应用实例 createApp(App).mount(#app) 这句话意思是以App作为参数生成一…

ElasticSearch备考 -- Search scroll

一、题目 Search for all documents in all indices As above, but use the scroll API to return the first 100 results while keeping the search context alive for 2 minutes Use the scroll id included in the response to the previous query and retrieve the next ba…

启用vnc访问Dell 服务器IDRAC 7虚拟控制台

Dell IDRAC 7 版本太老,SSL证书过期,IDRAC的Java和本地远程虚拟机控制台访问不了,怎么办? 可以启用vnc访问IDRAC 虚拟控制台

Vue2如何在网页实现文字的逐个显现

目录 Blue留言: 效果图: 实现思路: 代码: 1、空字符串与需渲染的字符串的定义 2、vue的插值表达式 3、函数 4、mounted()函数调用 结语: Blue留言: 在国庆前夕,突发奇想,我想…

SAP HCM 自定义累计期间

需求是按3月~8月,9月~次年2月,做为累计期间,怎么处理?