为什么在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似乎不让你比较intObject ,而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)进行比较。 但就是这样。

如果在intFloat之间进行比较, Float将首先被拆箱,以便比较在floatint之间。 用其他方法做是没有意义的 – box int然后检查Integer的标识( Float不小于)。