栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

为什么此方法重载模棱两可?

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

为什么此方法重载模棱两可?

它无法在JDK 1.5、1.6和1.7中进行编译,但可以在JDK 1.8中工作。

更新 :这似乎是一个事实,即它与第一JDK8版本的工作实际上是一个错误:它曾在JDK
1.8.0_05,但根据这个问题,并通过medvedev1088答案,这个代码将 不会 再在1.8.0_25编译,这是符合JLS的行为

我认为这不是已修复的错误。相反,它是与Java 8中lambda表达式的方法调用机制相关的更改的影响。

大多数人可能会同意,关于“方法调用表达式”的部分是迄今为止Java语言规范中最复杂,最难以理解的部分。可能会有整个工程师团队负责交叉检查和验证此部分。因此,任何陈述或任何试图进行的推理都应花费大量的盐。(即使来自上述工程师)。但我会尝试一下,至少充实其他人可能会参考以进行进一步分析的相关部分:

考虑有关

  • JLS 7中的方法调用表达式
  • JLS 8中的方法调用表达式

并且考虑到这两种方法都是“潜在适用方法”(JLS7
/
JLS8),则相关的小节是关于

  • 阶段3:确定JLS7中适用的可变Arity方法
  • 阶段3:确定JLS8中可变Arity调用可应用的方法

对于JLS 7,它指出

当且仅当满足以下所有条件时,方法m是 适用的可变对数方法

  • 对于1 = i <n,可以通过方法调用转换将ei的类型Ai转换为Si。

(其他条件指的是此处不相关的调用形式,例如,真正 使用 varargs的调用或涉及泛型的调用)

参见示例:当可以通过方法调用转换将其转换为相应的形式方法参数时,方法适用于

b
类型的实际参数表达式。根据有关JLS7中方法调用转换的相应部分,允许进行以下转换:
Byte``b

  • 身份转换(第5.1.1节)
  • 不断扩大的原始转换(第5.1.2节)
  • 扩展参考转换(第5.1.5节)
  • 装箱转换(第5.1.7节),然后可选地扩大参考转换
  • 取消装箱转换(第5.1.8节),然后可以选择加宽原始转换。

显然,根据此规范,可以采用 两种 方法:

  • m(Number b, Number ... a)
    通过扩展参考转换适用
  • m(byte b, Number ... a)
    通过拆箱转换适用

您提到您 “ …发现扩展优先级高于拆箱” ,但这在此处不适用:上面列出的条件不涉及任何“优先级”。它们被列为不同的选项。即使第一种方法是

voidm(Byte b, Number ... a)
适用的,“身份转换”也将适用,但是它仍然仅算作 一种 可能的转换,并且由于含糊不清而导致错误方法。


因此,据我所知,这解释了为什么它 不适 用于JDK7。我没有详细弄清楚它为什么 没有 工作,JDK8。但是,在JLS
8中,可变可变方法的适用性的定义在“可变可变调用的适用方法的识别”中发生了细微变化:

如果m不是通用方法,则对于1≤i≤k,或者ei在宽松的调用上下文中与Ti兼容,或者ei与适用性无关(第15.12.2.2节),则m可通过可变arity调用来应用。

(我尚未深入研究“松散调用上下文”和第15.12.2.2节的定义,但这似乎是关键的区别)


顺便说一句,再次提到您 “ …发现扩展优先级比拆箱优先” 的说法:对于
涉及varargs(并且根本不需要方法调用转换)的方法,这是正确的。如果您在示例中遗漏了变量,那么查找匹配方法的过程将从阶段1:确定适用于子类型的匹配Arity方法开始。该方法由于是的子类型,因此

m(Numberb)
已经适用于该参数。没有理由进入第2阶段:确定适用于方法调用转换的匹配Arity方法。在此阶段,通过从以下位置取消装箱来进行方法调用转换
Byteb``Byte``Number
Byte
byte
将适用,但从来没有达到这个阶段。



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/573979.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号