Java重载方法如何竞争
突然想起以前遇到的一道笔试题,题目大概是这样子的
// 父类
public class Father {
}
// 子类
public class Son extends Father {
}
// 调用方
public class Main {
private static void run(Father father) {
System.out.println("Father");
}
private static void run(Son son) {
System.out.println("Son");
}
public static void main(String[] args) {
Father son = new Son();
run(son);
}
}
问:以上代码的运行结果是什么?
我们先把这个题目放一边,现在把这个问题扩展一下
public class Main {
// 重载1
private static void run(int param) {
System.out.println("int");
}
// 重载2
private static void run(long param) {
System.out.println("long");
}
// 重载3
private static void run(Integer param) {
System.out.println("Integer");
}
// 重载4
private static void run(Long param) {
System.out.println("Long");
}
// 重载5
private static void run(float param) {
System.out.println("float");
}
// 重载6
private static void run(double param) {
System.out.println("double");
}
// 重载7
private static void run(Object param) {
System.out.println("Object");
}
// 重载8
private static void run(int... param) {
System.out.println("int...");
}
public static void main(String[] args) {
run(1);
}
}
- 以上的代码运行结果是什么?
- 如果把重载1方法注释掉,运行结果是什么?
- 如果把重载1、2、3、4这4个方法注释掉,运行结果是什么?
以上的8个重载的方法,在调用者看来,如果传入一个“范围”较小的参数,比如传入参数1,好像所有方法在单独情况下都可以调用,但是在所有方法都存在的情况下,又不知道要怎么选择。调用重载方法遵循的优先级从高到低如下:
(1)精确匹配
比如传入了参数1,默认情况1是int类型的数据,那么就会调用run(int param)方法,这个没有什么疑问。而一开始的面试题也是这种情况,变量son是一个Father类型的对象,会调用run(Father father)方法从而运行结果是Father。
(2)如果是基本类型(8种),向上转为更大范围
我们都知道一个int类型的数据和一个long类型的数据运算,会先把int类型的数据隐式转换为long类型,再进行运行,结果得到一个long类型;一个long类型和一个float类型做运算,long类型会先转换为float类型;一个float类型和一个double类型运算,float类型会先转换为double型。重载方法也是同样的道理,如果没有精确的类型,会向上找,如果把重载1方法注释掉之后,会调用run(long param),如果也没有重载2,就会调用run(float param),以此类推。
(3)通过自动拆箱和装箱
假如重载1、2、5、6都被注释了,就会找自动装箱的参数,int自动装箱是Integer,也就是会调用run(Integer param)。
(4)通过子类向上继承路线依次匹配
比如以上的例子注释掉重载1、2、3、5、6之后,调用的是run(Object param),而不是run(Long param),因为Long不是Integer的父类。
(5)通过可变参数匹配
如果1、2、3、4条规则都没法匹配到方法,就会匹配可变参数,可变参数的竞争优先级是很低的。比如以上例子把重载1、2、3、5、6、7都注释掉,就会调用run(int... param)方法。
再看另一个例子
public class Main {
private static run(int param1, Integer param2) {}
private static run(Integer param1, int param2) {}
public static void main(String[] args) {
run(1, 2);
}
}
以上代码的运行结果是什么?
其实,上面的代码会编译报错,因为编译器不知道调用的时候到底是要把1自动装箱还是要把2自动装箱,调用的时候需要显式传入Integer类型的对象,而不是让编译器进行自动装箱操作,比如调用第一个方法时可以用run(1, Integer.valueOf(2)),同理,想要调用方法2时用run(Integer.valueOf(1), 2)。
说了那么多其实我们了解就行了,建议在实际的开发中尽量避免出现这样的重载方法,可以根据参数的不同改用不一样的方法名,因为这种写法其实和i++ + ++i一样会使得代码的可读性极差。
Java重载方法如何竞争的更多相关文章
- JAVA 重载方法,参数为NULL时,调用的处理 (精确性原则)
引子:大家可以思考一下下面程序的输出结果 public class TestNull { public void show(String a){ System.out.println("St ...
- java重载方法的二义性
http://blog.csdn.net/lavor_zl/article/details/40746813
- Java之方法重载篇(我重载了,你要如何来调用我。。)
一.课前引言 请看一下代码,你发现什么特殊之处了吗? public class MethodOverload { public static void main(String[] args) { ...
- Java 中方法的重载
问: 什么是方法的重载呢? 答: 如果同一个类中包含了两个或两个以上方法名相同.方法参数的个数.顺序或类型不同的方法,则称为方法的重载,也可称该方法被重载了.如下所示 4 个方法名称都为 show , ...
- Java中方法的重载
Java 中方法的重载 问: 什么是方法的重载呢? 答: 如果同一个类中包含了两个或两个以上方法名相同.方法参数的个数.顺序或类型不同的方法,则称为方法的重载,也可称该方法被重载了.如下所示 4 个方 ...
- 【细说Java】方法重载的简单介绍
1. 什么是重载 方法名称相同,但它们的参数类型或个数不同,这样,方法在被调用时编译器就可以根据参数的类型与个数的不同加以区分,这就是方法的重载. 既然可以通过参数类型或参数个数来作为重载条件,那返回 ...
- 为什么Java不能以返回值区分重载方法?
读者可能会想:"在区分重载方法的时候,为什么只能以类名和方法的形参列表作为标准呢?能否考虑用方法的返回值来区分呢?" 比如下面两个方法,虽然他们有相同的名字和形式参数,但却很容易区 ...
- Java基础-方法重载和方法重写的区别
什么是java方法重载 (1) 方法重载是让类以统一的方式处理不同类型数据的一种手段.多个同名函数同时存在,具有不同的参数个数/类型. 重载Overloading是一个类中多态性的一种表现. (2) ...
- java的方法重载
1丶java的方法重载特性 满足以下条件的两个或多个方法构成“重载”关系:(1)方法名相同 (2)参数类型不同,参数个数不同或者参数类型的顺序不同 像System.out.println一样,就是重载 ...
随机推荐
- DVWA之SQL Injection
SQL Injection SQL Injection,即SQL注入,是指攻击者通过注入恶意的SQL命令,破坏SQL查询语句的结构,从而达到执行恶意SQL语句的目的.SQL注入漏洞的危害是巨大的,常常 ...
- UVA11636复制粘贴
#include<stdio.h> int main() { int Cas = 1 ,n; while(~scanf("%d" ,&n) & ...
- Windows下包管理工具Bower的安装和使用
目录 安装Bower Bower的使用 安装Bower Windows下安装Bower之前,先安装好 nodejs 和 msysgit 环境 然后我们就可以使用npm包管理工具下载并全局安装bower ...
- C#-WiFi共享
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...
- base标签的作用
base标签可以自定义当前页面的相对路径,不受浏览器当前地址栏的影响,以base标签定义的地址为准 (只对相对路径起作用) <head> <meta charset="UT ...
- 拿到列表的长度len(列表名)
拿到列表的长度len(列表名),即元素个数 列表要放在括号里面
- Spring的Xml和JavaConfig 扩展你选哪一个?
引言 上一篇文章我们有怎么介绍到如何通过XML的形式来定义Spring的扩展<Spring面试高频题如何:自定义XML schema 扩展>,好多人都在吐槽现在都什么年代了,xml还有人再 ...
- [Qt] 事件机制(三)
在主窗口Widget中增加几个小功能 1.点击左键,在左上角label中显示"haha",点击右键,显示"lala" 在widget.h中添加: 1 #incl ...
- hugboy源库
=[个人整理的一些源库,均来自网络]= -[Ubuntu]- #阿里源 Ubuntu 20.04 deb http://mirrors.aliyun.com/ubuntu/ focal main re ...
- nginx 的三种虚拟主机配置方法
nginx三种虚拟主机配置的方法. 基于端口 在生产环境中一般使用端口或者域名. [root@web01 /etc/nginx/conf.d]# cat web01.conf server { lis ...