关于以下程序的输出结果

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:令人混淆的构造器案例
本谜题呈现给你了两个容易令人混淆的构造器。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强制你在不同的重载版本之间进行选择,那么请将实际的参数转型为你希望调用的重载版本的形式参数所具有的类型。

关于java重载函数,参数为null时,调用的处理。(精确性原则)相关推荐

  1. Java获取函数参数名称

    原理 编译之后的class文件默认是不带有参数名称信息的,使用 IDE 时,反编译jar包得到的源代码函数参数名称是 arg0,arg1......这种形式,这是因为编译 jar 包的时候没有把符号表 ...

  2. 【Groovy】Groovy 方法调用 ( Java 中函数参数是接口类型 | 函数参数是接口类型 可以 直接传递闭包 )

    文章目录 一.Java 中函数参数是接口类型 二.函数参数是接口类型 可以 直接传递闭包 三.完整代码示例 一.Java 中函数参数是接口类型 在 Android 中经常使用如下形式的接口 : 定义一 ...

  3. java rectangle_rectangle函数参数 java中Rectangle 的用法

    rectangle()函数 void rectangle(int left,int top,int right,int bottom) 说明: 参数le此函数调用方式为void rectangle(i ...

  4. java 重载 : 1.参数个数不同,2.参数类型不同

    参数个数相同时,参数类型需要不同,即使是不同变量名也不行.和是和变量的个数或者是变量的类型有关系  如果相同的话是覆盖 会报错 重载(overloading) 是在一个类里面,方法名字相同,而参数不同 ...

  5. Lua的函数参数为table时奇特现象

    前言 今天在工作中使用lua编写代码时发生了一个有趣的现象,特此记录一下. 问题再现 当lua的函数为table时会发生什么情况,话不多说直接上代码: local tb = {1, 2, 3}func ...

  6. JAVA重载函数求最大值

    重载函数求最大值 //找出两个整型数,三个整型数或四个整型数中的最大值 public class Example{static int max(int a,int b) {if(a>b) {re ...

  7. 函数定义、函数参数、跨脚本调用函数

    2.6.函数使用 函数定义 示例(文件名称为func1.sh): #!/bin/bash ##定义函数 hello() { echo "Hello there today's date is ...

  8. java中3|4_关于java:函数参数中3个点的含义是什么?

    本问题已经有最佳答案,请猛点这里访问. 我在读Android文档中的AsyncTask. private class DownloadFilesTask extends AsyncTask { pro ...

  9. Java中函数参数不固定的问题

    如何声明一个函数,既能接收单个参数,又可以接收多个参数呢?多个参数的个数是不固定的. 需要使用int ...param的方法,jvm会自动把他转换成int数组的方式,查看class类的反编译文件可以看 ...

最新文章

  1. 写给云栖社区在做网站的朋友一点干货
  2. Enda 的 2015 下半年读书计划
  3. Flutter 混合开发实战问题记录(三)打包并上传flutter aar(包含三方plugin) 到maven...
  4. [Java基础]注解概念
  5. 工作经常使用的SQL整理,实战篇(一)
  6. 架构解读丨Volcano作业资源预留设计原理
  7. Python的小数据存储,用什么格式更有逼格?
  8. 使用Python完美管理和调度你的多个任务
  9. 物联网智能电影院- Android
  10. Python读取nc文件
  11. 中国电信物联网平台使用笔记8:获取物联网平台数据1
  12. 数学史上10个备受质疑的伟大时刻
  13. 在centos中运行出现错误:cannot find -lbz2
  14. 京东商品详情查询接口V1新版接口
  15. Linux上一个恶意程序分析实例:一步一步揭开病毒程序的面纱1
  16. 郭霖博客出大事了,而鸿阳大神的博客现在情况暂时还好。
  17. CameraView Android 相机预览控件
  18. MATLAB计算杨氏模量,基于MATLAB处理动态图像的杨氏模量测量方法.doc
  19. 迪士尼照片_如何更改您的迪士尼+个人资料图片
  20. 快递单上关键信息开始“隐身” 个人信息不再“裸奔”

热门文章

  1. php过滤style,PHP过滤各种html标签
  2. thttpd支持php吗,轻量型thttpd+php5
  3. Android ADT Templates Android常用模版
  4. 永州计算机职称考试网,永州2016年11月职称计算机考试时间
  5. CentOS7部署Nginx
  6. MVC数据验证原理及自定义ModelValidatorProvider实现无编译修改验证规则和错误信息...
  7. 机房三维(3D)监控系统和机房可视化动力环境监控系统两者有什么特点?
  8. bootstrap-pagination demo
  9. 自动编译 打包 签名 android程序
  10. apache配置好后编译rewrite