我觉得这些是适用的:
JLS 15.12.2.4. Phase 3: Identify Methods Applicable by Variable Arity Invocation
JLS 15.12.2.5. Choosing the Most Specific Method
但是JLS语言太复杂了,我无法理解这一点。
void f(Integer... arg) { System.out.println("Integer..."); }
void f(int... arg) { System.out.println("int..."); }
void test() {
f((short)1); // int... called
f(1); // c.ERR
我似乎理解那个(除此之外已经回答了 here ),尽管答案没有描述整个重载解决方案的所有细节(确切的顺序 - 尝试了哪些参数)过程 - 无论如何,我的问题主要在第二个代码片段中(int .. vs long ......)。但让我详细介绍一下上面的片段:
f((short)1)
- 没有精确匹配,所以原始 short 首先被加宽(没有找到匹配),然后 short 被装箱成 Short(没有找到精确匹配), Short 被加宽(Number, Object) - 不匹配,现在进入第三阶段 (varargs) => 尝试以下内容:
- 短...(不完全匹配 => 尝试原始加宽)
- int...(找到完全匹配的 ,但不要停止,进一步搜索!)
- long..., float..., double...(不匹配 => 尝试装箱)
- 短...、数字...、对象...
因为没有找到其他匹配项 - 它编译正常。
f(1)
- 没有完全匹配,所以原始 int 首先被加宽(没有找到匹配),然后 int 被装箱到 Integer(没有找到完全匹配),Integer 被加宽(Number, Object) - 不匹配,现在进入第三阶段 (varargs) => 尝试以下内容:
- int...(找到了完全匹配的 ,但不要停止,进一步搜索!)
- long..., float..., double...(不匹配 => 尝试装箱)
- 整数...(现在不明确),数字...,对象...
由于找到了两个可能的匹配项 - 我们遇到了编译错误。
void f(long... arg) { System.out.println("long..."); }
void f(int... arg) { System.out.println("int..."); }
void test() {
f((byte)1); // int... called
f(1); // int... called
}
f(byte)
- 第三阶段 (varargs) => 尝试了以下内容:
- byte...(不匹配 => 尝试原始加宽)
- short..., int...(找到匹配项,但要进一步观察),long...(应该是模棱两可的错误,但事实并非如此! ), float..., double...(现在还进行装箱并随后扩大引用范围,以寻找更多可能的匹配项来标记编译错误“不明确”)
- 字节...、数字...、对象...
由于找到了两个可能的匹配项 - 应该是编译错误(但事实并非如此)。
我的猜测是有 4 个过程(精确原始匹配、原始扩展、装箱和精确引用匹配、引用扩展),如果在某个过程中找到匹配项,编译器将停止(该过程不会继续) , 但会尝试所有其他后续过程。在这种情况下,编译器在过程 2 处停止(仅 int... 匹配,但不匹配 long...),过程 3 和 4 没有产生匹配。
上面引用的answer在 SO 上提供以下标准:
for one parameter to be more specific than the other, the type of that parameter must be a subtype of the other method's parameter.
它可能适用于引用类型,但不适用于原始类型。
我好像明白了15.12.2.编译时步骤 2:确定方法签名。但就我而言,我们有“第三阶段 (§15.12.2.4) 允许将重载与可变元数方法、装箱和拆箱相结合。” - 但问题在于细节。
最佳答案
至于评论
for one parameter to be more specific than the other, the type of that parameter must be a subtype of the other method's parameter.
请注意,这适用于基本类型,请参阅 https://docs.oracle.com/javase/specs/jls/se8/html/jls-4.html#jls-4.10 规范中给出的关系暗示 int 是比 long 更具体的类型。
来自 https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.12.2.5
A type S is more specific than a type T for any expression if S <: T (§4.10).
关于java - 确切的重载解决程序 - 为什么 f(1) 调用 f(int...arg) 和 f(long...arg) 没有歧义?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57536610/