引子:大家可以思考一下下面程序的输出结果

public class TestNull {
public void show(String a){
System.out.println("String");
}
public void show(Object o){
System.out.println("Object");
}
public static void main(String args[]){
TestMain t = new TestMain();
t.show(null);
}
}

运行的结果是:

String

解释(主要是重载函数调用时精确性的问题):
《java解惑》这本书谜题46解释了这种情况。下面内容摘自《Java解惑》

谜题46:令人混淆的构造器案例
本谜题呈现给你了两个容易令人混淆的构造器。main方法调用了一个构造器,但是它调用的到底是哪一个呢?该程序的输出取决于这个问题的答案。那么它到底会打印出什么呢?甚至它是否是合法的呢?

public class Confusing {
private Confusing(Object o) {
System.out.println("Object");
}
private Confusing(double[] dArray) {
System.out.println("double array");
}
public static void main(String[] args) {
new Confusing(null);
}
}

传递给构造器的参数是一个空的对象的引用,因此,初看起来,改程序好像应该调用参数类型为Object的重载版本,并且将打印出Object。另一方面,数组也是引用类型,因此Null也可以应用于类型是double[]的重载版本。由此可能会得出结论:

  这个调用是模棱两可的,改程序应该是不能编译的

如果你试着去运行程序,就会发现我之前的直观猜测是不对的:该程序打印 的是

double array

这种行为有悖常理,但是有一个很好的理由可以解释它,

一:选取所有可获得的并可以应用的构造器或方法

二:在第一步选取的方法或者构造器中选择最精确的一个 ,二第二个方法就是缺乏精确性

  在我们的程序中,两个构造器都是可获得 并且可应用的。构造器Confusing(Object)可以接受任何传递给Confusing(double[ ])的参数,因此Confusing(Object)相对缺乏精确性。(每一个double数组都是一个Object,但是每一个Object并不一定是 一个double数组。)因此,最精确的构造器就是Confusing(double[ ]),这也就解释了为什么程序会产生这样的输出。

理解本谜题的关键在于在测试哪一个方法或构造器最精确时,这些测试没有使用实际的参数:即出现在调用中的参数。这些参数只是被用来确定哪一个重载版本是可应用的。一旦编译器确定了哪些重载版本是可获得且可应用的,它就会选择最精确的一个重载版本,而此时使用的仅仅是形式参数:即出现在声明中的参数。

要想用一个null参数来调用Confusing(Object)构造器,你需要这样写代码:

以这种方式来在多个重载版本中进行选择是相当令人不快的。在你的API 中,应该确保不会让客户端走这种极端。理想状态下,你应该避免使用重载:为不同的方法取不同的名称。当然,有时候这无法实现,例如,构造器就没有名称,因 而也就无法被赋予不同的名称。然而,你可以通过将构造器设置为私有的并提供公有的静态工厂,以此来缓解这个问题[EJ Item 1]。如果构造器有许多参数,你可以用Builder模式[Gamma95]来减少对重载版本的需求量。
如果你确实进行了重载,那么请确保所有的重载版本所接受的参数类型都互不兼容,这样,任何两个重载版本都不会同时是可应用的。如果做不到这一点,那么就请确保所有可应用的重载版本都具有相同的行为[EJ Item 26]。
总之,重载版本的解析可能会产生混淆。应该尽可能地避免重载,如果你必须进行重载,那么你必须遵守上述方针,以最小化这种混淆。如果一个设计糟糕的API强制你在不同的重载版本之间进行选择,那么请将实际的参数转型为你希望调用的重载版本的形式参数所具有的类型。

参考文档:https://blog.csdn.net/liusrblog/article/details/8088305

JAVA 重载方法,参数为NULL时,调用的处理 (精确性原则)的更多相关文章

  1. 错误笔记 对象为null时调用改对象的方法会报错

    对象为null时调用改对象的方法会报错

  2. 新手容易混乱的String+和StringBuffer,以及Java的方法参数传递方式。

    之前在交流群里和猿友们讨论string+和stringbuffer哪个速度快以及Java的方法参数传递的问题,引起了群里猿友的小讨论.最终LZ得出的结果是string+没有stringbuffer快, ...

  3. java 方法参数-值调用,引用调用问题

    (博客内容来自于core java卷一) 1. xx调用:程序设计语言中方法参数的传递方式: 引用调用(call by reference):表示方法接收的是调用者提供的变量地址. 值调用(call ...

  4. java中方法参数的一些总结(1)

    1.问题说明        在C++中,函数调用时有传值调用和传址调用两种方式,但在Java中只有传值调用一种方式.Java中的方法参数为那几种基本数据类型的情况跟C++中一样,传入的只是变量的拷贝. ...

  5. Spring框架Controller层(表现层)针对方法参数是Bean时HttpServletRequest绑定参数值问题解释

    在做项目的时候,有一个需求是将数据库中的信息封装到实体类返回到jsp界面 传过来的参数只是实体类的id属性,然后根据id属性去查数据库,事情就是这样,然后 结果遇到很奇怪的事情,在jsp页面中使用EL ...

  6. Java重载方法如何竞争

    突然想起以前遇到的一道笔试题,题目大概是这样子的 // 父类 public class Father { } // 子类 public class Son extends Father { } // ...

  7. Java获取方法参数名、Spring SpEL解析

    @Test public void testParse() { //表达式解析 ExpressionParser expressionParser = new SpelExpressionParser ...

  8. learning java Objects.requireNonNull 当传入参数为null时,该方法返回参数本身

    System.out.println(Objects.hashCode(obj)); System.out.println(Objects.toString(obj)); System.out.pri ...

  9. Java Map释放内存置null以及调用clear()的区别

    今天自己在总结map的时候,想到了在释放Map对象空间的时候就有使用过将Map对象置null,也有时候会调用clear()将Map中的数据清除,那么它们都有什么区别呢? Map<Integer, ...

随机推荐

  1. 不引用第三方变量交换a和b的值

    方法一:(可操作字符) a = a^b; b = a^b; a = a^b; 方法二:(可操作字符) a=a+b; b=a-b; a=a-b; 方法三:(不可以操作字符) a=a*b; b=a/b; ...

  2. 2019年北航OO第四单元(UML任务)及学期总结

    第四单元两次作业总结 第十三次作业 需求分析 本次作业需要完成一个UML类图解析器,所需要解析的只有符合UML标准和能够在Java 8中复现的UML类图.查询指令存在两种:仅与所查对象有关的指令,以及 ...

  3. 最短路&查分约束

    [HDU] 1548 A strange lift 根蒂根基最短路(或bfs)★ 2544 最短路 根蒂根基最短路★ 3790 最短路径题目 根蒂根基最短路★ 2066 一小我的观光 根蒂根基最短路( ...

  4. HDU 4344

    其实不过是大整数分解... 注意两点:注意L 不能==N 但是,N却可以是素数...囧 #include <iostream> #include <cstdio> #inclu ...

  5. POJ--2112--Optimal Milking【Floyd+Dinic+二分答案】

    链接:http://poj.org/problem?id=2112 题意:有k个挤奶器.编号1~k,c头牛,编号k+1~k+c,每一个挤奶器最多能给m头牛挤奶,给你一个k+c的邻接矩阵.要求每头牛都能 ...

  6. 深入浅出CChart 每日一课——快乐高四第九课 于无声处,CChart内置功能介绍之数据存取篇

    笨笨长期以来一直使用Origin软件画图和处理数据,但Origin软件没有编程语言的接口.笨笨开发CChart的一个潜在的目标.是想实现Origin软件的功能.当然这是一个不可能达到的目标.Origi ...

  7. hadoop无法启动DataNode问题

    因为种种原因,今天又一次安装hadoop集群.清空了/tmp下的文件夹,重新启动集群,hadoop namenode -format 之后  start-all   可是没有发现DataNode的守护 ...

  8. html与JacaScript中的重要思想:预留后路、向后兼容、js分离

    以一个简单的web程序为例 详细设计模式请配合代码及凝视食用 <!DOCTYPE html> <!-- 1 预留退路:假设用户禁用了js.链接还能正常显示吗?(href) 2 分离j ...

  9. HDU1237 简单计算器 【栈】+【逆波兰式】

    简单计算器 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Subm ...

  10. [POI 2007] 旅游景点

    [题目链接] https://www.lydsy.com/JudgeOnline/problem.php?id=1097 [算法] 首先,用Dijkstra算法求出2-k+1到每个点的最短路 然后,我 ...