为什么在Java 7中有一个int-to-object比较有效,但是在Java 8中却不是这样?
以下代码,
private boolean compare(Object a, int b) { return a == b; }
在Java 7中编译,但在Java 8中导致以下错误:
无与伦比的types:int和Object
看下面的问题:
在Java 7中比较Object和int
Java 6和Java 8似乎不让你比较int
和Object
,而7。 有没有关于这个的任何文件?
我对通知这些决定的背景知识感兴趣。 似乎他们还没有决定什么的。
我正在使用IntelliJ IDEA 14.1.4和JDK 1.7.0.51。
Java 7将自动装箱应用于int。
private boolean compare(java.lang.Object, int); Code: 0: aload_1 1: iload_2 2: invokestatic #2 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; 5: if_acmpne 12 8: iconst_1 9: goto 13 12: iconst_0 13: ireturn
我用build 1.7.0_71-b14
创build了这个
编辑:
这种行为被Oracle公认为是一个错误:
JDK-8013357 :Javac接受错误的二进制比较操作
相关的JLS部分是15.21。 Javac似乎将此视为参考比较,但仅当两个操作数是参考types时才允许参考比较。
…
JLS Section 15.21中的二进制比较的types规则现在将由javac正确执行。 从JDK5开始 ,javac已经接受了一些程序的Object-primitive比较,这些比较根据JLS 15.21不正确地input。 现在这些比较将被正确识别为types错误。
JLS – 第15章。Equality Operators提到了3个不同的==
运算符: 数字 , 布尔值和引用 。 在您的示例中, ==
运算符都不会发生,所以我们认为该声明是非法的 。
让我们来看看为什么==
不能在你的例子中应用:
-
15.21.2。 布尔相等运算符==和!=
没有必要提到为什么它不相关..
-
15.21.3。 引用平等运算符==和!=
如果等于运算符的操作数既是引用types又是空types,则操作是对象相等的。
如果无法通过转换转换(第5.5节 )将任一操作数的types转换为另一操作数的types,则会出现编译时错误。 两个操作数的运行时间值必然不相等。
-
15.21.1。 数值相等运算符==和!=
如果等于运算符的操作数都是数字types的,或者一个是数字types,另一个是可转换的( §5.1.8 )到数字types,则在操作数( §5.6.2 )上执行二进制数字提升。
现在让我们假设它是合法的,编译器将该行更改为:
if (a == new Integer(b))
你期望的结果是什么? 该条件永远不会被评估为true
,所以这是一个在Java 8中修复的bug 。
我无法得到一个例子来编译(固定bool→布尔)与javac 1.7.0_75,也没有与javac 1.8.0_60。 我没有JDK6,但我认为它不应该在那里工作。 也许这是一个早期的ecj不兼容性,正如Axel所暗示的,或者是一个不同的次要版本的javac中的错误。
无论如何,如果它起作用,这是由于自动装箱。 为了准备Java 8,这可能已经缩短了,因为stream和自动assembly不太好。
根据JLS 7 ,它不应该编译。 int
可以与盒装数字types(即Byte,Short,Character,Integer,Long,Float,Double)进行比较。 但就是这样。
如果在int
和Float
之间进行比较, Float
将首先被拆箱,以便比较在float
和int
之间。 用其他方法做是没有意义的 – box int
然后检查Integer
的标识( Float
不小于)。