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

// 父类
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. [CTF]中那些脑洞大开的编码和加密

    [CTF]中那些脑洞大开的编码和加密 摘自:https://www.cnblogs.com/mq0036/p/6544055.html 0x00 前言 正文开始之前先闲扯几句吧,玩CTF的小伙伴也许会 ...

  2. 【vue-07】vue-router

    Vue-router官网 安装 vue-router是一个插件包,所以我们还是需要用npm 来进行安装.打开命令行工具,进入你的项目目录,输入下面命令. npm install vue-router ...

  3. 大学四年因为分享了这些软件测试常用软件,我成了别人眼中的(lei)大神(feng)!

    依稀记得,毕业那天,我们辅导员发给我毕业证的时候对我说"你可是咱们系的风云人物啊",哎呀,别提当时多开心啦????,嗯,我们辅导员是所有辅导员中最漂亮的一个,真的???? 不过,辅 ...

  4. 前端基础问题:CSS vertical-align 属性

    CSS vertical-align 属性与基线的那些事~ 定义和用法: vertical-align 属性设置元素的垂直对齐方式. vertical-align只对内联元素(inline.inlin ...

  5. iNeuOS工业互联平台,WEB组态(iNeuView)增加动态图元,例如液位

    目       录 1.      概述... 2 2.      平台演示... 2 3.      应用过程... 2 4.      实现动态图元的效果... 3 1.   概述 最近,有潜在用 ...

  6. printf/scanf格式

    (1)打印字符 char c; printf("%c",c); (2)打印整形 int i; printf("%d",i); //有符号十进制数 printf( ...

  7. RTTI之typeid运算符

    1 #include <iostream> 2 #include <cstdlib> 3 #include <ctime> 4 #include <typei ...

  8. gcc 版本

    $ gcc --versiongcc (Ubuntu 5.4.0-6kord1~16.04.4k2) 5.4.0 20160609Copyright (C) 2015 Free Software Fo ...

  9. 使用 dd 命令进行硬盘 I/O 性能检测

    使用 dd 命令进行硬盘 I/O 性能检测 作者: Vivek Gite 译者: LCTT DongShuaike | 2015-08-28 07:30   评论: 1 收藏: 6 如何使用dd命令测 ...

  10. docker容器中日志文件过大处理方法

    背景 :在日常工作中一个基于centos镜像构建起来的python爬虫程序,日志文件在两个月内到了500G,日志存放在根目录下面,在不扩容的情况下把这个问题给解决掉.通过定时任务和脚本的方法,定期的清 ...