在Java中为什么不同的返回类型不算方法重载?
本文已收录《Java常见面试题》:https://gitee.com/mydb/interview
方法重载是指在同一个类中,定义了多个同名方法,但每个方法的参数类型或者是参数个数不同就是方法重载。
比如以下 4 个 method 方法就可以称之为方法重载,如下代码所示:
public class OverloadExample {
public void method() {
// doSomething
}
public void method(String name) {
// doSomething
}
public void method(Integer id) {
// doSomething
}
public void method(Integer id, String name) {
// doSomething
}
}
为什么不同返回类型不算方法重载?
要回答这个问题,首先要了解一点前置内容,方法签名。
方法签名是由:方法名称 + 参数类型 + 参数个数组成的一个唯一值,这个唯一值就是方法签名,而 JVM(Java 虚拟机)就是通过这个方法签名来决定调用哪个方法的。
从方法签名的组成规则我们可以看出,方法的返回类型不是方法签名的组成部分,所以当同一个类中出现了多个方法名和参数相同,但返回值类型不同的方法时,JVM 就没办法通过方法签名来判断到底要调用哪个方法了,如下图所示:

那为什么返回类型不能做为方法签名的一部分呢?
原因其实很简单,试想一下,如果方法的返回类型也作为方法签名的一部分,那么当程序员写了一个代码去调用“重载”的方法时,JVM 就不能分辨要调用哪个方法了,如下代码所示:
public class OverloadExample {
public static void main(String[] args) {
OverloadExample example = new OverloadExample();
example.method("磊哥"); // JVM 应该调用哪个方法?
}
public int method(String name) {
// doSomething
return 666;
}
public String method(String name) {
// doSomething
return "磊哥聊编程";
}
}
像以上情况,JVM 就推断不出来要调用哪个方法了,所以方法的返回类型不能作为方法签名的一部分。
方法重载的使用场景
方法重载的经典使用场景是 String 类型的 valueOf 方法,valueOf 方法重载有 9 种实现,如下图所示:

它可以将数组、对象和基础数据类型转换成字符串类型。
方法重载匹配原则
方法重载的调用顺序是有前后之分的,比如以下代码:
public class OverloadExample {
public static void main(String[] args) {
OverloadExample example = new OverloadExample();
example.method(12);
}
public void method(int num) {
System.out.println("调用 int 方法");
}
public void method(long num) {
System.out.println("调用 long 方法");
}
public void method(Integer num) {
System.out.println("调用 Integer 方法");
}
public void method(Object num) {
System.out.println("调用 Object 方法");
}
public void method(int... num) { // 可选参数
System.out.println("调用 int... 方法");
}
}
当出现方法重载时,程序要调用哪个方法呢?执行以上程序的执行结果如下:

因此我们可以得出以下结论。
匹配原则1:精准类型匹配
方法重载会优先调用和方法参数类型一模一样的方法,这是第一优先匹配原则:精准类型匹配。
匹配原则2:基本类型自动转换成更大的基本类型
接下来我们把精准匹配方法删掉,观察一下第二匹配顺序是什么?实现代码如下:
public class OverloadExample {
public static void main(String[] args) {
OverloadExample example = new OverloadExample();
example.method(12);
}
public void method(long num) {
System.out.println("调用 long 方法");
}
public void method(Integer num) {
System.out.println("调用 Integer 方法");
}
public void method(Object num) {
System.out.println("调用 Object 方法");
}
public void method(int... num) { // 可选参数
System.out.println("调用 int... 方法");
}
}
以上程序的执行结果如下图所示:

因此我们可以得出结论:如果是基本数据类型,那么方法重载调用的第二匹配原则是自动转换成更大的基本数据类型。
匹配原则3:自动装/拆箱匹配
接下来将第二匹配原则中的 long 方法也删除掉,实现代码如下:
public class OverloadExample {
public static void main(String[] args) {
OverloadExample example = new OverloadExample();
example.method(12);
}
public void method(Integer num) {
System.out.println("调用 Integer 方法");
}
public void method(Object num) {
System.out.println("调用 Object 方法");
}
public void method(int... num) { // 可选参数
System.out.println("调用 int... 方法");
}
}
以上程序的执行结果如下图所示:

从上述执行结果可以看出,方法重载的第三匹配原则是,匹配自动装箱或拆箱的数据类型。
匹配原则4:按照继承路线依次向上匹配
此时将第三匹配原则中的 Integer 方法删除,剩下代码如下:
public class OverloadExample {
public static void main(String[] args) {
OverloadExample example = new OverloadExample();
example.method(12);
}
public void method(Object num) {
System.out.println("调用 Object 方法");
}
public void method(int... num) { // 可选参数
System.out.println("调用 int... 方法");
}
}
以上程序的执行结果如下图所示:

从上述执行结果可以看出,方法重载的第四匹配原则是,依次向上匹配父类的方法调用。
匹配原则5:可变参数匹配
最后将代码中的方法删除的只剩一个可选参数,实现代码如下:
public class OverloadExample {
public static void main(String[] args) {
OverloadExample example = new OverloadExample();
example.method(12);
}
public void method(int... num) { // 可选参数
System.out.println("调用 int... 方法");
}
}
以上程序的执行结果如下图所示:

从上述执行结果可以看出,方法重载的第五匹配原则是,匹配可选参数。
总结
在同一个类中定义了多个同名方法,但每个方法的参数类型或者是参数个数不同就是方法重载。方法重载的典型使用场景是 String 中的 valueOf 方法,它有 9 种实现。方法返回类型不能作为方法重载的依据,因为它不是方法签名的组成部分。方法重载有 5 个匹配原则:精准匹配、基本类型自动转换成更大的基本类型匹配、自动装/拆箱匹配、按照继承路线依次向上匹配、可变参数匹配。
参考资料:《码出高效》
是非审之于己,毁誉听之于人,得失安之于数。
公众号:Java面试真题解析
在Java中为什么不同的返回类型不算方法重载?的更多相关文章
- java中相同名字不同返回类型的方法
这种名字相同返回类型不同的方法,在同一个类中是无法共存的,不论是继承过来的方法,还是多实现过来的方法,在一个类内都无法共存.名字确定了,你能改的只有参数(重载).
- (转) Java中的负数及基本类型的转型详解
(转) https://my.oschina.net/joymufeng/blog/139952 面这行代码的输出是什么? 下面两行代码的输出相同吗? 请尝试在Eclipse中运行上面的两个代码片段, ...
- 【转】java中byte数组与int类型的转换(两种方式)----不错
原文网址:http://blog.csdn.net/piaojun_pj/article/details/5903009 java中byte数组与int类型的转换,在网络编程中这个算法是最基本的算法, ...
- java中读取特殊文件的类型
java中读取特殊文件的类型: 第一种方法(字符拼接读取): public static String getType(String s){ String s1=s.substring(s.index ...
- Java中的基本类型和包装类型区别
首先看一下几个测试题,验证一下java中对基本类型和包装类型的理解,看看最后输出的答案对不对,答案在这篇博客中哦: // 第一题: 基本类型和包装类型 int a = 100; Integer b = ...
- Java中的两种异常类型及其区别?
Java中的两种异常类型是什么?他们有什么区别? Throwable包含了错误(Error)和异常(Excetion两类) Exception又包含了运行时异常(RuntimeException, 又 ...
- JAVA中如何获取变量的类型
JAVA中如何获取变量的类型? package xiya; public class Demo { public static void main(String[] args) { String ty ...
- java中如何理解:其他类型 + string 与 自增类型转换和赋值类型转换
java中如何理解:其他类型 + string 与 自增类型转换和赋值类型转换 一.字符串与其他类型连接 public class DemoString{ public static void mai ...
- Java执行shell脚本并返回结果两种方法的完整代码
Java执行shell脚本并返回结果两种方法的完整代码 简单的是直接传入String字符串,这种不能执行echo 或者需要调用其他进程的命令(比如调用postfix发送邮件命令就不起作用) 执行复杂的 ...
随机推荐
- Mysql多字段模糊查询
MySQL同一字段多值模糊查询 一. 同一字段多值模糊查询,使用多个or进行链接,效率不高,但没有更好的解决方案.(有看到CHARINDEX 关键字,可查询结果并不是模糊,举个栗子 例如SELECT ...
- pop和push等使用方法,every和some、join
push 在最前面添加一个元素 pop 移除最后一个元素 shift 移除第一个元素 unshift 放入一个元素,且排在最前 arr.splice(2,2)//移除从指定下标 slice(2 ...
- C++内存管理:new / delete 和 cookie
new 和 delete C++的内存申请和释放是通过 new 和 delete 实现的, 而new 和 delete 其实就是通过 malloc 和 free 实现的. new 申请内存分为三个步骤 ...
- postgresql很强大,为何在中国,mysql成为主流?
你找一个能安装起来的数据库,都可以学,不管什么版本. 数据库的基本功,是那些基本概念(SQL,表,存储过程,索引,锁,连接配置等等),这些在任何一个版本中都是一样的. 目录 postgresql很强大 ...
- 记一次AWD
有幸bjx师傅又让我参加了一次awd,算是第二次体验awd,又感觉学习到了很多东西. 第一次打这种模式的时候,我几乎什么都没有做,就给师傅们下载文件,上传文件了.(太菜了) 昨晚分的组,发现没有人是p ...
- jenkins+docker+k8s项目发布
目录 一.简介 二.新建docker-build工程 三.项目部署 四.访问测试 一.简介 1.该章节基于jenkins.Harbor.pipeline.k8s来做发布,如对这些不熟悉,请按以下进入学 ...
- TFTP协议介绍-python实现tftp客户端
1. TFTP协议介绍 TFTP(Trivial File Transfer Protocol,简单文件传输协议) 是TCP/IP协议族中的一个用来在客户端与服务器之间进行简单文件传输的协议 特点: ...
- 不同机房vpc使用openswan打通内网
1.测试环境: 北京6云主机:120.92.51.75/10.0.3.13 VPC:10.0.0.0/16 Ren-test 上海2云主机:42.157.163.120/192.168.3.3 ...
- 解决VMware开机黑屏问题
最近搞虚拟机.一直遇见了许多问题.发现某一天.VMware开机后.其中一个虚拟机直接卡住黑屏了.关的时候就一直显示.xxx繁忙.无法关闭.网上搜到了解决方法.这边记录一下. 1.关闭所有服务 2.修复 ...
- MyBatis学习(三)MyBatis基于动态代理方式的增删改查
1.前言 上一期讲到MyBatis-Statement版本的增删改查.可以发现.这种代码写下来冗余的地方特别多.写一套没啥.如果涉及到多表多查询的时候就容易出现问题.故.官方推荐了一种方法.即MyBa ...