`

今天面试居然选错了一道题

    博客分类:
  • java
阅读更多
比如:

package com.bjsxt;

public class Test2 {

public void info(Object obj) {
System.out.println("obj");
}

public void info(String str) {
System.out.println("str");
}

/**
* @param args
*/
public static void main(String[] args) {
Test2 T2 = new Test2();
T2.info(null);
}

}打印出:str



解释(主要是重载函数调用时精确性的问题)

《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强制你在不同的重载版本之间进行选择,那么请将实际的参数转型为你希望调用的重载版本的形式参数所具有的类型。
分享到:
评论

相关推荐

    记录一道面试算法题餐馆问题(贪心和动态规划) 贪心算法和动态规划.pdf

    记录一道面试算法题餐馆问题(贪心和动态规划) 贪心算法和动态规划.pdf

    北大方正软件测试工程师面试题

    北大方正以下是一位软件测试培训学员整理的北大方正软件测试工程师面试...乙到2层,照这样计算,当甲到9层时,乙到(D)层 A.5B.6C.7D.8 2、有一份选择题试卷共6个小题,其得分标准是:一道小题答对得8分,答错得0分,

    Kaggle上入门比赛以及一道云客公司的机器学习面试题.zip

    机器学习是一门多领域交叉学科,涉及概率论、统计学、逼近论、凸分析、算法复杂度理论等多门学科。...在实际应用中,需要根据具体问题和需求选择合适的机器学习算法和模型,并进行适当的优化和调整。

    Java泛型单元试题.html

    精选java关于泛型的原理,应用和面试题,包含所有泛型考点。例如,泛型的概念,类型,实例化,容易混淆的用法。每一道题附上答案,方便理解考试要点。

    逻辑思维1200题(扫描版).pdf

    《逻辑思维训练1200题》是...读者可以根据自己的实际情况逐步训练,也可以有选择地学习和训练,从而激发推理潜能、活跃思维、提升逻辑思维能力,挑战公务员、MBA等各类考试,突破世界500强面试,让你的人生更上一层楼。

    逻辑思维训练1200题

    也有复杂的游戏,每一道训练题都是为全方位培养和训练读者的逻辑思维方法专门设计的,引导读者亲身实践这些方法的应用。同时,编者还按照不同的难易程度将题目分为初级、中级和高级3个等级,读者可以根据自己的实际...

    每日采访问题:我是木易杨,公众号“高级前端进阶”作者,每天搞定一道前端大厂面试题,祝大家天天进步,一年后会看到不一样的自己

    推荐扫码使用微信小程序,除了本项目之外,还囊括了算法题,选择题等多种类型变量和详细解析记住我们的口号:上下班路上刷一点,半年突击进大厂今日面试题第162题:实现对象的地图函数类似Array.prototype.map解析:...

    逻辑思维1200题(扫描版)

    《逻辑思维训练1200题》是...读者可以根据自己的实际情况逐步训练,也可以有选择地学习和训练,从而激发推理潜能、活跃思维、提升逻辑思维能力,挑战公务员、MBA等各类考试,突破世界500强面试,让你的人生更上一层楼。

    fe-interview-handwrite:前端面试常见手写题整理

    前端面试手写题整理前端面试常见的手写题,面试出现概率极高,建议每个都过自己过一遍。你也可以提交 PR,提供你面试遇到的题目。代码汇总请参照 。高频:★★★ 中频:★★ 低频:★JavaScript 原理 ★★ ★★ ★★...

    C/C++面试题目及解答.doc

    <br>对于字符串拷贝来说,用上述三个函数都可以实现,但是其实现的效率和使用的方便程度不同: • strcpy 无疑是最合适的选择:效率高且调用方便。 • snprintf 要额外指定格式符并且进行格式转化,麻烦且...

    leetcode中文版-2020_NA_HighFrequency_OA:此Repo完全开源用于交流分享最热门的北美线上面试高频题以及电话面试

    每一道提交的题目和题解请依照以下格式 1. 题号 (请自觉顺延#1, #2 etc.) 2. 题目描述 (请保证题目描述具有完整的逻辑性并保证高可读性, 中文为优) 3. 边界范围 (可选,但一个合适的题目应该拥有合理的边界条件,...

    模拟双色球筛选过程生成随机数

    在一道面试题上看到如何得到一组随机数,彼此不重复,然后就自己敲敲代码,跟大伙分享下。

    c++ 如何合并两个有序链表

    这是一道求职面试时经常要求手写或者机试的经典题目。 已知两个链表head1和head2各自有序,请把它们合并成一个链表依然有序。结果链表要包含head1和head2的所有节点,即使节点值相同。 注意:不能开辟新空间来存储...

    leetcode2-LeetCode_Python:LeetCode与python从1到∞

    每周刷LeetCode一道题(从easy开始),至少坚持两年半 不求快,不满足于AC 至少用两种思路实现,争取用最简短的代码实现 解释一下: 0、为什么要搞这个专栏? 1)就业形势严峻,怕被淘汰 2)整理记录我的收获、复习...

    leetcode怎么计算空间复杂度是指-final-battle:最后一战

    最后一道算法题,0-25表示A-Z,给一个数字字符串,求有多少种解码方式(dp问题,思路对了,关键步骤没写对,直接挂了) 链接: 一直在问faster rcnn,faster rcnn RPN流程,anchor选的太大或太小有什么影响,正负...

    python入门到高级全栈工程师培训 第3期 附课件代码

    python入门到高级全栈工程师培训视频学习资料;本资料仅用于学习,请查看...11 强插一道面试题 12 Model连表操作梳理 13 多对多自关联 14 Model操作补充 15 再插两道JavaScript面试题 16 Model操作之select_related以及...

Global site tag (gtag.js) - Google Analytics