评论由:alexmiller 提供
在第一种情况下,-10000000000000 是 long 类型,编译器明确找到 Math.abs(long)。
在第二种情况下,a 是 Object 对象,考虑所有 abs 签名(这在 Reflector.invokeMatchingMethod 中)。在 Java 1.7 和 1.8 中,都有找到 long 和 int 签名 "一致"。
在 Java 1.7 中,首先找到 long 版本并处理为匹配项,然后检查 int,Compiler.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中出现应归功于运气,而不是意图。