突然想起以前遇到的一道笔试题,题目大概是这样子的

// 父类
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重载方法如何竞争的更多相关文章

  1. JAVA 重载方法,参数为NULL时,调用的处理 (精确性原则)

    引子:大家可以思考一下下面程序的输出结果 public class TestNull { public void show(String a){ System.out.println("St ...

  2. java重载方法的二义性

    http://blog.csdn.net/lavor_zl/article/details/40746813

  3. Java之方法重载篇(我重载了,你要如何来调用我。。)

      一.课前引言 请看一下代码,你发现什么特殊之处了吗? public class MethodOverload { public static void main(String[] args) { ...

  4. Java 中方法的重载

    问: 什么是方法的重载呢? 答: 如果同一个类中包含了两个或两个以上方法名相同.方法参数的个数.顺序或类型不同的方法,则称为方法的重载,也可称该方法被重载了.如下所示 4 个方法名称都为 show , ...

  5. Java中方法的重载

    Java 中方法的重载 问: 什么是方法的重载呢? 答: 如果同一个类中包含了两个或两个以上方法名相同.方法参数的个数.顺序或类型不同的方法,则称为方法的重载,也可称该方法被重载了.如下所示 4 个方 ...

  6. 【细说Java】方法重载的简单介绍

    1. 什么是重载 方法名称相同,但它们的参数类型或个数不同,这样,方法在被调用时编译器就可以根据参数的类型与个数的不同加以区分,这就是方法的重载. 既然可以通过参数类型或参数个数来作为重载条件,那返回 ...

  7. 为什么Java不能以返回值区分重载方法?

    读者可能会想:"在区分重载方法的时候,为什么只能以类名和方法的形参列表作为标准呢?能否考虑用方法的返回值来区分呢?" 比如下面两个方法,虽然他们有相同的名字和形式参数,但却很容易区 ...

  8. Java基础-方法重载和方法重写的区别

    什么是java方法重载 (1) 方法重载是让类以统一的方式处理不同类型数据的一种手段.多个同名函数同时存在,具有不同的参数个数/类型. 重载Overloading是一个类中多态性的一种表现. (2)  ...

  9. java的方法重载

    1丶java的方法重载特性 满足以下条件的两个或多个方法构成“重载”关系:(1)方法名相同 (2)参数类型不同,参数个数不同或者参数类型的顺序不同 像System.out.println一样,就是重载 ...

随机推荐

  1. hdu5007 小水题

    题意:       给你一个串,如果出现子串 "Apple", "iPhone", "iPod", "iPad"输出MA ...

  2. 手脱UPX3.91壳(练习)

    0x01 准备 OD UPX加壳程序 可以加壳的软件 0x02 给软件加壳 我找了半天发现winhex不错,而且是没壳的可以直接加壳 1.复制一份可执行文件 将赋值好的文件用UPX3.91加壳 0x0 ...

  3. 模板templates的使用

    目录 模板及其渲染 模板查找路径 DTL模板语法 常用的模板标签 DTL常用过滤器 模块结构优化 加载静态文件 模板及其渲染 视图函数只是直接返回文本,而在实际生产环境中其实很少这样用,因为实际的页面 ...

  4. Intel汇编语言程序设计学习-第六章 条件处理-中

    6.3  条件跳转 6.3.1  条件结构 在IA-32指令集中没有高级的逻辑结构,但无论多么复杂的结构,都可以使用比较和跳转指令组合来实现.执行条件语句包括两个步骤:首先,使用CMP,AND,SUB ...

  5. openstack虚拟机从数据库修改卷虚拟机backend操作

    由于意外故障,volume-type其中一个backend后段出现性能问题,客户云主机出现卡顿. 因此临时从ceph将系统卷导出,并导入至同一个backend的另一个后端,并启动虚拟机. Nova C ...

  6. 【python】Leetcode每日一题-森林中的兔子

    [python]Leetcode每日一题-森林中的兔子 [题目描述] 森林中,每个兔子都有颜色.其中一些兔子(可能是全部)告诉你还有多少其他的兔子和自己有相同的颜色.我们将这些回答放在 answers ...

  7. 鼠标右键添加vscode

    实现效果 右键文件夹,可以使用vscode打开 右键文件,可以使用vscode打开 右键空白处,可以使用vscode打开 进行实现 下载压缩包 为了方便操作,和减少错误,将.reg文件上传到网盘中,点 ...

  8. Windows进程间通讯(IPC)----信号量

    线程同步内核对象 操作系统进行进程间同步是利用信号量机制.对于windows系统而言,可以利用一些内核对象进行线程同步,因为这些内核对象可以命名并且属于系统内核,所以可以支持不同进程间的线程同步进而实 ...

  9. 语音降噪论文“A Hybrid Approach for Speech Enhancement Using MoG Model and Neural Network Phoneme Classifier”的研读

    最近认真的研读了这篇关于降噪的论文.它是一种利用混合模型降噪的方法,即既利用了生成模型(MoG高斯模型),也利用了判别模型(神经网络NN模型).本文根据自己的理解对原理做了梳理. 论文是基于" ...

  10. 分布式锁为什么要选择Zookeeper而不是Redis?

    在分布式的应用中,为了防止单点故障,保障高可用,通常会采用主从结构,当主节点挂掉后,从节点可以代替主节点提供服务. Redis通过复制 + sentinel哨兵来实现主从模式. Zookeeper通过 ...