评论者:alexmiller
在第一种情况下,-10000000000000 是 long 类型,编译器明确找到 Math.abs(long)。
在第二种情况下,a 是 Object 类型,所有 abs 签名都被考虑(这是在 Reflector.invokeMatchingMethod 中)。在 Java 1.7 和 1.8 中,long 和 int 签名都被找到“一致”。
在 Java 1.7 中,long 版本首先找到并被视为匹配项,然后检查 int,Compileer.subsumes((link: int), (link: long)) 返回 false,导致 long 方法被保持为匹配项。
在 Java 1.8 中,int 版本首先找到并被视为匹配项,然后检查 long,Compiler.subsumes((link: long), (link: int)) 返回 false,导致 int 方法被保持为匹配项。
这两个在两个 JDK 上都返回 false
(Compiler/subsumes (into-array [Long/TYPE]) (into-array [Integer/TYPE])) (Compiler/subsumes (into-array [Integer/TYPE]) (into-array [Long/TYPE]))
所以真正的区别只是考虑的顺序,这是 JDK 相关的。
考虑的签名可以通过某些规范方式进行排序,以使此行为一致,或者也许可以通过某种方式表达对两个签名之间的偏好。
无论如何,通过提示或强制类型转换来消除这里的反射可以解决问题 - 我认为,在这种情况下,Java 7得到的正确结果更多的是运气而非意图。