由 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得到正确的结果只是一种运气,而非意图。