方法重载与方法重写差别

写在开头

请聊一聊Java中方法的重写和重载?

这个问题应该是各大厂面试时问的最多的话题之一了,它们几乎贯穿了我们日常的开发工作,在过往的博客中我们多多少少都提到过重载重写,而今天我们就一起来详细的学习一下这二者的功能与区别!

重载与重写的定义

重写: 类实现接口或者子类继承父类时,保持方法签名相同,用不同的方法体来实现不同的功能,这也是Java三大特性之一多态的具体实现,是垂直方向的“类间行为”。

重载: 在同一个类或者父类与子类之间,保持方法名称相同,参数类型,参数数量,参数顺序不同的一种实现,是水平方向上的“类内行为”,同一个类中,或者父子类中。

方法的重写

如下代码中是一个最简单的重写的实现

public class Dog extends Animal{
    public static void main(String[] args) {
        Dog dog = new Dog();
        dog.method1();
    }
    @Override
    public void method1() {
        System.out.println("狗子爱奔跑");
    }
}
class Animal {
    public void method1(){
        System.out.println("我是动物!");
    };
}

重写的规则

1、重写发生在子类继承父类
2、参数列表必须完全与被重写方法的相同
3、重写父类方法时,修改方法的权限只能从小范围到大范围
4、返回类型与被重写方法的返回类型可以不相同,但是必须是父类返回值的子类(JDK1.5 及更早版本返回类型要一样,JDK1.7 及更高版本可以不同)
5、访问权限不能比父类中被重写的方法的访问权限更低。如:父类的方法被声明为 public,那么子类中重写该方法不能声明为 protected
6、重写方法不能抛出新的检查异常和比被重写方法申明更宽泛的异常(即只能抛出父类方法抛出异常的子类)
7、声明为 final 的方法不能被重写
8、声明为 static 的方法不能被重写
9、声明为 private 的方法不能被重写

【补充说明】
上面的9条规则中,前面6条应该没什么太多的疑问,访问权限、异常声明范围,子类小于父类,就如同包含与被包含关系,狗子(子类)是动物(父类),那它所拥有的一切自然都要在动物的范畴内!
第7条,final关键字修饰的方法,一旦初始化引用不可变,具体可参考之前发的这篇文章
面试官:小伙子来说一说Java中final关键字
第8点,static修饰的方法不能被重写,这也是一个考点,很好理解,static修饰的方法属于类方法,在调用的时候直接通过类名.方法名即可,而重写也就是多态是基于对象的,一个静态的方法不会联系到任何实例上,所以也就不存在重写了!但是很多面试官为了考验应聘着的细心,会紧接着问一句,那子类中可以有一个和父类方法签名一致的静态方法吗?

答案是肯定的,如果父类中含有一个静态方法,且在子类中也含有一个返回类型、方法名、参数列表均与之相同的静态方法,那么该子类实际上只是
将父类中的该同名方法进行了隐藏,而非重写。 换句话说,父类和子类中含有的其实是两个没有关系的方法,它们的行为也并不具有多态性。

static关键字内容,可以看这篇文章:深入理解Java中的static关键字

第9条就更没什么好说的了,private表示方法是本类私有,其他类均不可见,更不可能重写了。

方法的重载

重载是发生在编译期间的一种静态绑定,编译器通过方法签名来定位具体重载的哪个方法,如String的valueOf就是一个方法重载的案例典范,上代码!

目前String中valueOf重载的方法已多达十几种,用以实现不同的数据类型转换为字符串的逻辑。

是不是觉得重载很简单?不就是方法名相同的情况下,传入不同参数即可调用不同的重载方法,那么我们看看下面的代码
 


这时若我们分别调用1、method(),2、method(1),3、method(1L),4、method(null),猜一下答案,嘿嘿
 


调用1时方法1和方法5均可满足条件(可变参数,参数个数为0或多个),但因为JVM重载方法时优先通过精准匹配进行选择,所以这里会选择方法1;调用2时,方法2、3、4、5均满足,同样因为精准匹配的原因,选择了方法2;调用3时,因为重载方法中没有参数为long类型的,所以会通过子类向上转型继承路线依次匹配,最终调用到了方法4;这里4的调用被注释掉了,原因是报错啦,出现了模糊匹配。
 


参数null可以匹配任何一个类对象,这里从满足从子类向上转型进行匹配,但在Integer和可变参数的选择上,编译器无法选择,所以编译报错。

由上述的例子其实我们不难看出,在多个重载方法均满足条件时,编译器对于重载的选择是有优先顺序的,下面进行了整理。

编译器选择顺序(从高到底)
精准匹配
基本数据类型,自动转换为更大范围的基本类型
通过装箱与拆箱进行匹配
通过子类向上转型继承路线依次匹配
通过可变参数匹配

重载的规则

1、被重载的方法参数列表(个数或类型)不一样
2、被重载的方法可以修改返回类型
3、被重载的方法可以修改访问修饰符
4、被重载的方法可以修改异常抛出
5、方法能够在同一个类中或者在一个子类中被重载
6、无法以返回值类型作为重载函数的区分标准

【补充说明】
以上6点规则中,前5点比较好理解,第6点也是很多面试官经常会追问的问题,为什么重载的方法,不能将返回值类型作为参考标准。
首先,我们看一下这段代码:

public class Dog {
    public int method1(int a,int b) {
        return a+b;
    }
    public short method1(int a,int b) {
        return (short)(a+b);
    }
}

这段代码中的两个方法,就是保持了返回值类型不同,但提示方法已经被定义,无法重载,说明仅靠返回值类型无法作为方法重载的参考标准!,仔细想想也很容易明白,并不是所有的方法都是有返回值的,难道无返回值的方法重载时,我们还要依赖返回值去判断?
​写到这里,俺又想到了一个问题,你们觉得main()方法可以重载吗

public class OverloadingMain {
    public static void main(String[] args) {
        System.out.println("String[] args");
    }

    public static void main(String args) {
        System.out.println("String args");
    }

    public static void main() {
        System.out.println("无参");
    }
}

输出:

String[] args

显然,重载是被允许的,但JVM在运行时,只会将那个参数为String[] args的静态main方法作为程序的入口,其他方法只能通过调用去实现打印结果!

重载与重写的区别

基于以上的分析,我们可以精炼出重载与重写的重要区别:
作用范围: 重写的作用范围是父类和子类之间;重载是发生在一个类里面
参数列表: 重载必须不同;重写不能修改
返回类型: 重载可修改;重写方法返回相同类型或子类
抛出异常: 重载可修改;重写可减少或删除,一定不能抛出新的或者更广的异常
访问权限: 重载可修改;重写一定不能做更严格的限制

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Elsevier】中科院2区SCI,仅3个月录用!接收领域广!

关注公主号【SciencePub学术】,发现期刊更多精彩~ 1 数据处理类SCIE(高质量) 【期刊简介】IF:6.5-7.0,JCR1区,中科院2区; 【出版社】Elsevier出版社 【版面情况】正刊,仅5篇版面…

jetson-inference----docker内运行分类任务

系列文章目录 jetson-inference入门 jetson-inference----docker内运行分类任务 文章目录 系列文章目录前言一、进入jetson-inference的docker二、分类任务总结 前言 继jetson-inference入门 一、进入jetson-inference的docker 官方运行命令 进入jetson-inference的docker d…

Github 2024-01-26 开源项目日报Top10

根据Github Trendings的统计,今日(2024-01-26统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Python项目4Jupyter Notebook项目2HTML项目1Shell项目1Dockerfile项目1非开发语言项目1Go项目1Rust项目1 高级…

最小覆盖子串(Leetcode76)

例题: 分析: 比如现在有字符串(s),s "ADOBECODEBANC", 给出目标字符串 t "ABC", 题目就是要从原始字符串(s)中找到一个子串(res)可以覆盖目标字符串 t &…

vue3预览pdf文件的几种方法

vue3预览pdf集中方法 方法一&#xff1a; iframe&#xff1a;这种方法显示有点丑 <iframesrc"E:\\1.pdf"frameborder"0"style"width: 80%; height: 100vh; margin: auto; display: block"></iframe>方法二&#xff1a; 展示效果&…

【C++】wxWidgets编程的程序入口点

在wxWidgets中&#xff0c;程序的入口点通过wxIMPLEMENT_APP宏定义来设置&#xff0c;该宏会扩展为一个实现了main函数或者在Windows上是WinMain函数的代码。wxIMPLEMENT_APP宏与wxDECLARE_APP宏一起使用来设置基于wxWidgets的应用程序的启动代码。 使用wxIMPLEMENT_APP宏通常是…

【AI Agent系列】【MetaGPT】9. 一句话订阅专属信息 - 订阅智能体进阶,实现一个更通用的订阅智能体(2)

文章目录 0. 前置推荐阅读和本文内容0.1 前置推荐阅读0.2 本文内容 1. 修改一&#xff1a;直接用大模型获取网页信息&#xff0c;不用爬虫程序1.1 我们要给大模型什么内容1.2 提取网页文本信息1.3 组织Action1.4 完整代码及细节注释1.5 可能存在的问题及思考 2. 修改二&#xf…

实体识别与分类方法综述

目录 前言1 实体识别简介2 基于模板和规则的方法3 基于序列标注的方法3.1 常见序列标注模型3.2 模型参数估计和学习问题3.3 常见序列预测模型 4. 基于深度学习的实体识别方法5 基于预训练语言模型的实体识别5.1 BERT、GPT等预训练语言模型5.2 解码策略 6 特殊问题与挑战6.1 标签…

视频渲染靠cpu还是显卡 会声会影视频渲染的作用是什么

视频渲染最占用的资源就是CPU&#xff0c;多核心多线程&#xff0c;这样才能渲染快。渲染可以在时间线上实时平滑预览&#xff0c;便于编辑&#xff0c;最终导出成片的时候速度也会快一些&#xff0c;渲染就是对每桢的图像进行重新优化的过程。 渲染的作用主要是能够保证使用者…

C#使用RabbitMQ-2_详解工作队列模式

简介 &#x1f340;RabbitMQ中的工作队列模式是指将任务分配给多个消费者并行处理。在工作队列模式中&#xff0c;生产者将任务发送到RabbitMQ交换器&#xff0c;然后交换器将任务路由到一个或多个队列。消费者从队列中获取任务并进行处理。处理完成后&#xff0c;消费者可以向…

outlook如何群发邮件?外贸邮件群发教程?

outlook邮箱群发邮件方法&#xff1f;outlook怎么设置邮件群发&#xff1f; 如果你正在使用Outlook&#xff0c;那么你一定想要知道如何有效地群发邮件。Outlook作为微软办公套件的一部分&#xff0c;不仅功能强大&#xff0c;而且操作简便。下面&#xff0c;蜂邮EDM就来详细讲…

vscode开发FPGA(1)---TEROS_HDL插件报错

一、TerosHDL:modelsim(vlog-66)报错 Error: (vlog-66) Execution of vlib.exe failed 解决办法&#xff1a; 1.新建modelsim工程&#xff0c;并随意编译一个.v文件&#xff0c;将产生的work目录复制到modelsim安装路径下。 2.再将vscode设置verilog>linting>modelsim…

vue3 + jeecgBoot 获取项目IP地址

封装的useGlobSetting 函数 引入并使用 import { useGlobSetting } from //hooks/setting;const glob useGlobSetting();console.log(glob.uploadUrl) //http://192.168.105.57:7900/bs-axfd

docker的资源限制(cgroup)

前瞻 Docker 通过 Cgroup 来控制容器使用的资源配额&#xff0c;包括 CPU、内存、磁盘三大方面&#xff0c; 基本覆盖了常见的资源配额和使用量控制。 Cgroup 是 ControlGroups 的缩写&#xff0c;是 Linux 内核提供的一种可以限制、记录、隔离进程组所使用的物理资源(如 CPU、…

uni-app 接口封装,token过期,自动获取最新的token

一、文件路径截图 2、新建一个文件app.js let hosthttp://172.16.192.40:8083/jeecg-boot/ //本地接口 let myApi {login: ${host}wx/wxUser/login, //登录 } module.exports myApi 3、新建一个文件request.js import myApi from /utils/app.js; export const r…

【云原生】Docker的镜像创建

目录 1&#xff0e;基于现有镜像创建 &#xff08;1&#xff09;首先启动一个镜像&#xff0c;在容器里做修改 ​编辑&#xff08;2&#xff09;然后将修改后的容器提交为新的镜像&#xff0c;需要使用该容器的 ID 号创建新镜像 实验 2&#xff0e;基于本地模板创建 3&am…

uniapp上传音频文件到服务器

视频教程地址&#xff1a; 【uniapp录音上传组件&#xff0c;将录音上传到django服务器】 https://www.bilibili.com/video/BV1wi4y1p7FL/?share_sourcecopy_web&vd_sourcee66c0e33402a09ca7ae1f0ed3d5ecf7c uniapp 录制音频文件上传到django服务器保存到服务器 &#xf…

svn和git的本质区别是什么

参考&#xff1a; https://blog.csdn.net/feiying0canglang/article/details/126550676 上边图中&#xff0c;跨越了区的箭头&#xff0c;它中间的区数据都会同步。例如&#xff1a;git checkout &#xff0c;它是将本地仓库数据更新到暂存区和工作区的。\ 理解 gitlab和svn都…

【深度优先搜索】【C++算法】834 树中距离之和

作者推荐 【动态规划】【map】【C算法】1289. 下降路径最小和 II 本文涉及知识点 深度优先搜索 树 图论 LeetCode834 树中距离之和 给定一个无向、连通的树。树中有 n 个标记为 0…n-1 的节点以及 n-1 条边 。 给定整数 n 和数组 edges &#xff0c; edges[i] [ai, bi]表…

【AIGC】Diffusers:训练扩散模型

前言 无条件图像生成是扩散模型的一种流行应用&#xff0c;它生成的图像看起来像用于训练的数据集中的图像。通常&#xff0c;通过在特定数据集上微调预训练模型来获得最佳结果。你可以在HUB找到很多这样的模型&#xff0c;但如果你找不到你喜欢的模型&#xff0c;你可以随时训…