关于java重载函数,参数为null时,调用的处理 (精确性原则)
来源:互联网 发布:mac格式化u盘 编辑:程序博客网 时间:2024/06/06 17:15
关于以下程序的输出结果
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
这种行为可能显得有悖常理,但是有一个很好的理由可以解释它。
Java的重载解析过程是以两阶段运行的:
第一阶段 选取所有可获得并且可应用的方法或构造器;
第二阶段在第一阶段选取的方法或构造器中选取最精确的一个。
如果一个方法或构造器可以接受传递给另一个方法或构 造器的任何参数,那么我们就说第一个方法比第二个方法缺乏精确性[JLS 15.12.2.5]。
在我们的程序中,两个构造器都是可获得 并且可应用的。构造器Confusing(Object)可以接受任何传递给Confusing(double[ ])的参数,因此Confusing(Object)相对缺乏精确性。(每一个double数组都是一个Object,但是每一个Object并不一定是 一个double数组。)因此,最精确的构造器就是Confusing(double[ ]),这也就解释了为什么程序会产生这样的输出。如果你传递的是一个double[ ]类型的值,那么这种行为是有意义的;但是如果你传递的是null,这种行为就有违直觉了。
理解本谜题的关键在于在测试哪一个方法或构造器最精确时,这些测试没有使用实际的参数:即出现在调用中的参数。这些参数只是被用来确定哪一个重载版本是可应用的。一旦编译器确定了哪些重载版本是可获得且可应用的,它就会选择最精确的一个重载版本,而此时使用的仅仅是形式参数:即出现在声明中的参数。
要想用一个null参数来调用Confusing(Object)构造器,你需要这样写代码:
new Confusing((Object)null)
这可以确保只有Confusing(Object)是可应用的。更一般地讲,要想强制要求编译器选择一 个精确的重载版本,需要将实际的参数转型为形式参数所声明的类型。
以这种方式来在多个重载版本中进行选择是相当令人不快的。在你的API 中,应该确保不会让客户端走这种极端。理想状态下,你应该避免使用重载:为不同的方法取不同的名称。当然,有时候这无法实现,例如,构造器就没有名称,因 而也就无法被赋予不同的名称。然而,你可以通过将构造器设置为私有的并提供公有的静态工厂,以此来缓解这个问题[EJ Item 1]。如果构造器有许多参数,你可以用Builder模式[Gamma95]来减少对重载版本的需求量。如果你确实进行了重载,那么请确保所有的重载版本所接受的参数类型都互不兼容,这样,任何两个重载版本都不会同时是可应用的。如果做不到这一点,那么就请确保所有可应用的重载版本都具有相同的行为[EJ Item 26]。
总之,重载版本的解析可能会产生混淆。应该尽可能地避免重载,如果你必须进行重载,那么你必须遵守上述方针,以最小化这种混淆。如果一个设计糟糕的API强制你在不同的重载版本之间进行选择,那么请将实际的参数转型为你希望调用的重载版本的形式参数所具有的类型。
0 0
- 关于java重载函数,参数为null时,调用的处理。(精确性原则)
- 关于java重载函数,参数为null时,调用的处理。(精确性原则)
- 关于java重载函数,参数为null时,调用的处理 (精确性原则)
- 关于java重载函数,参数为null时,调用的处理 (精确性原则)
- 关于java重载函数,参数为null时,调用的处理。(精确性原则)
- Java重载函数,当参数为null时,调用的处理
- Java重载,当参数为null时,调用情况
- 方法重载参数为null时处理方案
- Java中函数重载和null参数的传递
- 关于strdup函数参数为NULL的分析和建议
- java调用Kotlin方法的参数为null异常问题
- 解决 -- java 调用webservice 服务端收到参数为null
- sql server 里面的convert函数,当传入参数为null时,返回null
- C++关于参数为const引用类型的函数调用参数成员函数的一个问题
- springMVC 对参数为null或参数不为null的处理
- 关于函数模板重载的调用顺序
- 关于oracle采用pivot函数列转行后一些列的值为null处理
- Delphi 调用C#编写的WebService 参数为Null解决方法
- 数据库基础手札
- 基于itop4412的EC20在Android4.4的PPP拨号联网
- BJ模拟 Cut (最小割树+最小生成树)
- 常见的排序算法
- 物联网操作系统 微软 Windows IoT Core 与华为 LiteOS 对比
- 关于java重载函数,参数为null时,调用的处理 (精确性原则)
- Android Studio实用快捷键
- centos搭建openvpn经验
- jQuery Validate
- maven project中plugin配置错误的解决方法
- eclipse 生成javadoc编码错误解决方案
- LightOJ 1341Aladdin and the Flying Carpet(唯一分解定理)
- spring+mybatis dubbo 整合 sharding-jdbc分库分表存日志
- iOS获取本地时间和APP中显示时间XX分钟/小时之前