40从零开始学Java之方法重写和方法重载到底有哪些区别?

news2025/2/25 12:01:47

作者:孙玉昌,昵称【一一哥】,另外【壹壹哥】也是我哦

千锋教育高级教研员、CSDN博客专家、万粉博主、阿里云专家博主、掘金优质作者

前言

在前面的两篇文章中,壹哥给大家讲解了面向对象中的封装和继承,现在还有一个多态没有给大家讲到。但是在学习多态之前,我们需要提前知道“方法重写”是怎么回事,因为方法重写是实现多态的一个必要条件。所以如果我们不知道方法重写是咋回事,学习多态也就会有点费劲。废话少说,直接上干货!

--------------------------------------------------前戏已做完,精彩即开始----------------------------------------------

全文大约【4000】字,不说废话,只讲可以让你学到技术、明白原理的纯干货!本文带有丰富的案例及配图视频,让你更好地理解和运用文中的技术概念,并可以给你带来具有足够启迪的思考......

配套开源项目资料

Github:

GitHub - SunLtd/LearnJava

Gitee:

一一哥/从零开始学Java

一. 方法重写

在面向对象中,实现多态的必备条件是继承、重写和向上转型,现在我们已经学习了什么是继承。接下来我们再来学习什么是方法重写,这是我们能够实现多态的前提。

1. 概念

如果我们在子类中,创建了一个与父类中名称、返回值类型、参数列表都完全相同的方法,只是方法体的功能实现不同,这种方式被称为方法重写(override),或者叫方法覆盖。当父类中的方法无法满足子类的需求,或者子类需要有特殊功能时,就可以进行方法重写。

2. 基本要求

我们在进行方法重写时,需要遵循以下几点要求:

  • 父类的成员方法只能被它的子类重写,即不能继承一个方法,就不能重写这个方法;
  • 被final修饰的方法不能被重写;
  • 被static修饰的方法不能被重写,但可以再次声明;
  • 构造方法不能被重写;
  • 子类和父类在同一个包中时,子类可以重写父类中除了被private和final修饰的其他所有方法;
  • 子类和父类不在同一个包中时,子类只能重写父类被public和protected修饰的非final方法;
  • 重写的方法建议使用@Override注解来标识。

3. 注意事项

另外我们在进行方法重写时,还要注意以下几点:

  • 方法签名要相同:重写的方法和被重写的方法,在方法名、参数上都要相同;
  • 返回值类型一致:JDK 1.5之前重写方法的返回值类型必须一样,但之后的Java版本放宽了限制,返回值类型必须小于或等于父类方法的返回值类型
  • 访问修饰符要更宽泛:子类重写父类的方法时,子类方法中的访问修饰符不能比父类中的更严格(public>protected>default>private)。比如父类方法的修饰符是protected,则子类的同名方法其修饰符可以是protected或public,但不能是默认的或private;
  • 声明的异常类型要一致:重写的方法一定不能抛出新的检査异常,或者比被重写方法声明更宽泛的检査型异常。例如,父类的方法声明了IOException,重写该方法时就不能抛出Exception,只能拋出IOException或其子类异常,但可以抛出非检査异常

4. 代码实现

接下来壹哥就通过一个案例来给大家讲解方法的重写该怎么实现。

4.1 定义父类

我们先定义一个Father父类,要注意父类中有哪些方法不能被重写。

public class Father {
    // 父类中的成员变量--变量隐藏
	String name="老子";
	
	//构造方法不能被重写,因为构造方法不能被继承!
	public Father() {
		System.out.println("爹的构造方法");
	}

	// 吃
	public void eat() {
		System.out.println("爹吃馒头");
	}

	// 喝
	public void drink() {
		System.out.println("爹喝水");
	}
	
	// 玩
	//私有方法不能被重写
//	private void play() {
//		System.out.println("爹玩火");
//	}
	
	//静态方法不能被重写,但可以在子类中声明一个同样的静态方法。
//	public static void play() {
//		System.out.println("爹玩火");
//	}
	
	//final方法不能被重写
	public final void play() {
		System.out.println("爹玩火");
	}
}

4.2 定义子类

定义一个Son子类继承父类,有了继承才会有重写!

public class Son extends Father{
	//构造方法不能被重写,因为构造方法不能被继承!
	//@Override
	//public Father() {}

	// 吃
	/**
	 * 方法重写时可以带有@Ovriride关键词,当重写的方法签名不一致时,可以有编译错误的提示。
	 * 否则方法签名不一致时不会有错误提示,会被当做一个新的方法来处理。
	 */
	@Override
	public void eat() {
		//如果子类的功能,是在父类的基础之上进行的额外扩展增加,
		//我们可以使用super关键字调用父类的同名方法,然后再进行自己的额外扩展!
		//如果子类的实现和父类完全不一样,可以不调用super!
		super.eat();
		
		//方法重写时,子类可以对父类的同名方法进行扩展实现,方法体的内容可以和父类中的实现不一样
		System.out.println("儿子吃肉");
	}

	// 喝
	@Override
	public void drink() {
		//如果子类的实现和父类完全不一样,可以不调用super!
		System.out.println("儿子喝酒");
	}
	
	/**
	 * 父类私有的、static、final等方法无法被重写
	 */
	//@Override
	//public void play() {}
	
	//static静态的父类方法不能被重写,但可以在子类中再重新编写一个静态的同名方法。
	//public static void play() {}

    //变量隐藏--调用父类和子类中的同名成员变量
	public void sayHello() {
		// 如果子类的实现和父类完全不一样,可以不调用super!
		System.out.println("父亲的名字=" + super.name);
		System.out.println("儿子的名字=" + name);
	}

	public static void main(String[] args) {
		Son son = new Son();
		son.sayHello();
	}
}

我们在进行方法重写时,要注意以下几点:

  • 方法重写时可以带有@Ovriride关键词。当重写的方法签名不一致时,会有编译错误的提示,否则方法签名不一致时不会有错误提示,会被当做一个新的方法来处理。
  • 当子类对象调用重写的方法时,默认执行的是子类的方法,而不是父类中被重写的方法。如果我们想要调用父类中被重写的方法,则可以使用“super.方法名”的形式。
  • 如果子类的功能是在父类的基础之上进行的额外扩展,我们可以使用super关键字调用父类的同名方法,然后再进行自己的额外扩展!
  • 如果子类的实现和父类完全不一样,可以不调用super!
  • 方法重写时,子类可以对父类的同名方法进行扩展实现,方法体的内容可以和父类中的实现不一样。

4.3 @Override注解

在上面的代码中,我们用到了一个新的关键字@Override。在Java中,@Override是一个注解,关于注解的更多内容,壹哥会在后面的文章中进行专门讲解,现在我们先知道注解这个概念就行。

@Override是一个用来修饰被重新的方法的注解,只能用在被重新的方法上,不能用在其它的地方。该注解可以强制子类必须重写父类的方法或者接口中的方法,主要是告诉编译器检查重写的方法是否和父类中定义的一致。如果重写的方法签名不一致,会提示编译错误。如果方法签名不一致,则不会有错误提示,会被当做一个新的方法来处理。通过这样的机制,就可以避免程序员出现一些低级的错误。

5. 变量隐藏

5.1 概念

如果子类中定义了一个成员变量,而该变量的名称与父类中的成员变量相同,数据类型不一定完全一致,我们就把这称为变量隐藏。也就是说,子类的成员变量,对从父类继承过来的成员变量进行了重新定义,出现了子类变量对父类变量的隐藏。所以子类执行自己定义的方法时,操作的成员变量默认是自己定义的变量,而不是父类中的同名变量。如果我们非要操作隐藏的成员变量,可以使用super关键字进行调用。

接下来我们通过一个案例来给大家演示变量隐藏的使用。

5.2 案例实现

父类中定义一个成员变量name,如下图所示:

子类中也定义一个相同的成员变量name,如下图所示:

如果我们在Son类中直接使用name,默认使用的是Son自己的变量;如果我们想使用Father类中的name变量,则可以通过“super.属性”的形式进行。执行结果如下图所示:

6. 方法隐藏

在子类继承父类时,既然存在变量隐藏的现象,同理也存在方法隐藏的现象。

6.1 概念

我们知道,方法的重写是子类覆盖父类的对象方法,而方法隐藏则是子类覆盖父类的静态方法(类方法)。在java中的静态方法能被子类继承吗?答案是肯定的,但若子类中有与父类中同名同参的方法,则父类的方法将被隐藏。

6.2 案例实现

我们先定义一个Father父类,里面有个静态方法eat。

/**
 * @author 一一哥Sun 
 * 千锋教育
 * 定义父类
 */
public class Father {
	// 吃---静态方法
	public static void eat() {
		System.out.println("爹吃馒头");
	}
}

然后再定义一个Son子类,里面也有一个静态方法eat。我们知道,静态方法是可以被继承的,所以如果Son子类中没有定义自己的eat()方法,默认可以使用Father父类中的eat()方法。但如果我们在子类中也定义了一个eat()方法,子类的同名静态方法就会隐藏父类中的eat()方法,这就是方法隐藏。

/**
 * @author 一一哥Sun 
 * 千锋教育
 * 子类继承父类
 */
public class Son extends Father {
	// 吃---静态方法
    //如果子类中没有定义该方法,则子类可以继承使用父类的eat()方法
	public static void eat() {
		//子类覆盖父类中的同名静态方法(类)
		System.out.println("儿子吃肉");
	}
	
	public static void main(String[] args) {
		//调用子类自己的静态方法
		eat();
		//调用父类的静态方法
		Father.eat();
	}
}

执行结果如下图所示:

6.3 小结

通过本案例,我们可以得出以下结论:

  1. 子类可以继承父类中的静态方法;
  2. 子类无法重写父类中的静态方法,但可以重载;
  3. 若子类中定义了与父类中同样的静态方法,则父类的同名方法会被子类隐藏

二. 重写与重载的区别

在Java中既有方法重写(Override),也有方法重载(Overload),对于初学者来说很容易搞混。所以有不少面试官,在招聘初级程序员时,就很喜欢问我们方法重写与方法重载的区别。

其实方法重写Override和方法重载Overload的最大不同,在于方法签名的不同。如果同一个类中的多个方法签名不同,就是方法重载Overload,重载出的方法是一个新方法。如果父子类之间的多个方法签名相同,且返回值也相同,就是方法重写Override。

当然,如果你想把关于重写和重载的区别说得更详细,可以参考以下章节。

1. 重载的特点

  • 方法重载要求方法同名不同参(参数类型、个数、顺序);
  • 重载的方法与返回值、访问修饰符无关;
  • 重载的方法发生在同一个类中,是在一个类中创建多个同名的方法。

2. 重写的特点

  • 重写的方法发生在父子类中,需要有继承关系;
  • 父类的成员方法只能被它的子类重写,即不能继承一个方法,就不能重写这个方法;
  • 被final修饰的方法不能被重写;
  • 被static修饰的方法不能被重写,但可以再次声明;
  • 构造方法不能被重写;
  • 子类和父类在同一个包中时,子类可以重写父类中除了被private和final修饰的其他所有方法;
  • 子类和父类不在同一个包中时,子类只能重写父类被public和protected修饰的非final方法;
  • 方法重写时可以使用@Override注解;
  • 方法签名要相同
  • 返回值类型一致
  • 访问修饰符要更宽泛
  • 声明的异常类型要一致

------------------------------------------------​​​​​​​正片已结束,来根事后烟----------------------------------------------

三. 结语

现在你知道方法重写是怎么回事了吗?另外方法重载和方法重写的区别,是我们面试初级程序员时很常见的题目,大家一定要牢牢掌握哦。现在有了方法重写的基础,接下来我们就可以学习多态的内容了,敬请关注下一篇文章哦。

另外如果你独自学习觉得有很多困难,可以加入壹哥的学习互助群,大家一起交流学习。

四. 配套视频

如果你不习惯阅读技术文章,或是对文中的技术概念不能很好地理解,可以来看看壹哥帮你筛选出的视频教程。与本文配套的Java学习视频,链接如下:

Bilibili External Player

五. 今日作业

1. 第一题

设计一个父类和一个子类,让子类超越父类的能力。

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

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

相关文章

物联网开发愈加深化,如何保障应用安全?

在如今的iot物联网定制市场,许多产品都在“物物互联”,通过远程通信和连接设备来提供数据采集和处理能力。智能设备与智能家居、智慧城市等领域的结合也越发紧密。而对于企业而言,应用物联网设备时,也需要注意其中的安全问题。那么…

苹果WWDC 2023发布会总结

今年的全球开发者大会没有让人失望。在今天的主题演讲中,苹果首次展示了备受期待的混合现实耳机,证实了过去几个月出现的许多谣言。 虽然这次苹果的 Vision Pro耳机成为了焦点,但该公司还发布了一些其他令人兴奋的硬件和软件相关公告。这是活…

Java 泛型机制详解

tip:作为程序员一定学习编程之道,一定要对代码的编写有追求,不能实现就完事了。我们应该让自己写的代码更加优雅,即使这会费时费力。 推荐:体系化学习Java(Java面试专题) 文章目录 一、Java 中…

python中对excel工作表的基础操作:xlrd、xlwt模块笔记

模块介绍 (1)什么是xlrd模块? python操作excel主要用到xlrd和xlwt这两个库,即xlrd是读excel,xlwt是写excel的库。 (2)为什么使用xlrd模块? 在UI自动化或者接口自动化中数据维护是一…

突然断电没保存的文档如何找回?给你支几招!

概述:突然断电没保存的文档如何找回?我们在办公中经常会用到Word/PPT/EXCEL等文档,要是正在编辑时,电脑突然断电了,而文档还来得及保存怎么办?不要着急,下面教你找回未保存的文档。 一、突然断…

nodered-环境搭建及使用

nodered-环境搭建及使用 一、准备工作 - 安装node.js二、 nodered安装2.1 windows10环境下安装2.2 linux环境下安装 三、 nodered使用3.1 面板操作3.2 公共节点的使用3.3 上下文、全局变量 四、node缓存清理五、后台运行六、 nodered卸载 IBM发行了一套开源可视化界面开发工具&…

Hive学习---6、文件格式和压缩

1、文件格式和压缩 1.1 Hadoop压缩概述 由于Hive是相当于与Hadoop的客户端,所以hadoop会啥压缩,Hive基本就会啥压缩。 压缩格式算法文件扩展名是否可切分DEFLATEDEFLATE.deflate否GzipDEFLATE.gz否bzip2bzip2.bz2是LZOLZO.lzo是SnappySnappy.snappy否…

页面置换算法(LRU,CLOCK,LFU)

在操作系统的数据库中,使用驱逐算法来实现内存和磁盘之间的交互。当内存空间已满且需要将磁盘上的页面添加到内存中时,就需要将内存中的一个页面换出,以保证内存空间不会溢出。我们希望尽可能多地访问内存中的页面。 LRU算法 LRU算法&#…

0基础学习VR全景平台篇第38章:场景功能-AI虚拟人实操完整教程

AI虚拟人功能正式上线! 依托“虚拟数字人引擎”结合VR全景,为各行各业提供虚拟形象生成、驱动、交互服务,帮助海量用户的VR全景作品,打造成为更具沉浸感的VR交互项目,提升作品变现能力。 功能位置示意 一、什么是AI虚…

会声会影视频乱码什么原因 会声会影视频乱码怎么处理

会声会影编辑视频的过程中,如果遇到素材乱码的问题,是会让人十分崩溃的。毕竟素材来之不易,无论是重新下载还是重新录制素材,操作起来都是相当困难的。那么,会声会影视频乱码什么原因,会声会影视频乱码怎么…

C++设计模式之原型模式(Prototype)

[C]22种设计模式的C实现大纲 文章目录 定义别名前言1. 问题2. 解决方案 结构1. 基本实现2. 原型注册表实现 适用场景实现方式优点缺点与其他模式的关系实例 定义 原型是一种创建型设计模式,使你能够复制已有对象,而又无需使代码依赖它们所属的类。 别…

利用fabric绘画矩形和多边形

需求在一张图片上标注矩形和多边形,支持回显; fabric版本:4.6.0; Fabric.js 是一个功能强大且操作简单的 Javascript HTML5 canvas 工具库。 官方文档 参考链接 组件代码drawer.vue createUuid 是为了让每一个图形有自己的id&…

【 Python 全栈开发 - 语法基础篇 - 20 】数据可视化

文章目录 一、数据可视化二、pandas1. 折线图2. 散点图3. 柱状图4. 饼图 三、matplotlib1. 折线图2. 散点图3. 柱状图4. 饼图 四、seaborn1. 安装和导入Seaborn2. 加载数据集3. 绘制散点图4. 绘制直方图5. 绘制核密度图6. 绘制条形图7. 绘制热力图 五、plotly安装plotly创建图表…

chatgpt赋能python:如何重新运行Python程序:完整指南

如何重新运行Python程序:完整指南 Python是最受欢迎的编程语言之一,因为其语法简单易懂,使得编写高效可读性代码更加轻松。但在编程过程中经常会出现需要重新运行程序的情况,本文将为您介绍如何重新运行Python程序。 重新运行Py…

chatgpt赋能python:Python如何降低memory的方法

Python如何降低memory的方法 Python已经成为了世界上最流行的编程语言之一,它在开发web应用、机器学习、数据分析等领域中拥有广泛的应用。然而,由于Python的内存管理机制,可能会导致程序的内存占用过高,影响系统的性能。在本文中…

excel文档翻译软件怎么使用?告诉你怎么翻译整个excel文档

excel是一款电子表格软件,广泛应用于数据分析、统计和管理等领域。然而,当我们需要处理包含其他语言的excel文档时,可能会遇到语言障碍。不用担心,现在有一些方便的软件可以帮助我们轻松翻译excel文档。今天我们就一起来看看excel…

UniApp个人总结:新建页面大汇总

文章目录 往期回顾正文本篇目标环境安装如何新建模板页面页面布局推荐新建模板文件 总结 往期回顾 uniapp 踩坑记录 uni.$on为什么不能修改data里面的数据 uniApp页面通讯大汇总,如何页面之间传值 uniApp 页面通讯统一解决方案 uniapp sqlite 数据库操作封装 un…

一致性模型

首先明确一下分布式的组成定义,为下面打好铺垫 都做到了让系统“表现得像只有一个副本”。它们的不同在于,前一种排序遵循了不同用户的操作的时间先后顺序,而后一种排序没有。实际上,如果我们要求系统满足线性一致性,就…

什么是创新,为何如此难,又能解决啥-非AI撰写

什么项目创新?机器人技术创新?能解决下文中的问题呢? 这是近两个月以来,也许唯一一篇,我自己码字写的博客。 有感于一些课程,比如: 这一类课程最为典型的特点就是课程名称上有“创新”这两个字…

Matlab基础入门

Matlab简介 矩阵实验室(matrix&laboratory) R2022a:2022上半年的版本 R2022b:2022下半年的版本 Matlab界面 命令行窗口 与使用者直接进行交互,相当于一个计算器 >> 11ans 2 >> 5-2ans 3 >&…