为什么int-to-Object比较在Java 7中有效,而在Java 8中无效?

Mat*_*Bro 61 java

以下代码,

private boolean compare(Object a, int b) {
    return a == b;
}
Run Code Online (Sandbox Code Playgroud)

在Java 7中编译,但它导致Java 8中出现以下错误:

无与伦比的类型:int和Object

看看以下问题:

在Java 7中比较Object和int

这似乎像Java 6和Java 8,不要让你比较intObject,而7一样.有没有这方面的文件?

我对通知这些决定的背景知识很感兴趣.看起来他们还没有决定.

我正在使用IntelliJ IDEA 14.1.4和JDK 1.7.0.51.

wer*_*ero 30

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
Run Code Online (Sandbox Code Playgroud)

我创造了这个 build 1.7.0_71-b14

编辑:

Oracle认识到此行为并将其视为错误:
JDK-8013357:Javac接受错误的二进制比较操作

相关的JLS部分是15.21.Javac似乎将此视为参考比较,但仅当BOTH操作数是引用类型时才允许引用比较.
...
JLS第15.21节中的二进制比较的类型规则现在将由javac正确实施.从JDK5开始,javac接受了一些程序,这些程序的对象原语比较根据JLS 15.21输入错误.现在,这些比较将被正确识别为类型错误.


Mar*_*oun 22

所述JLS -第15章相等运算提到3个不同的==操作符:数值,布尔参考.的的==运营商可以在你的例子发生,所以我们得出结论,声明是非法的.

让我们看看为什么==不能在你的例子中应用:

现在让我们假设它是合法的,并且编译器将该行更改为:

if (a == new Integer(b))
Run Code Online (Sandbox Code Playgroud)

您对结果的期望是什么?这个条件永远不会评估true,因此它是一个在Java 8中修复的错误.

  • 但是,使用`Integer.valueOf`完成自动装箱.由于`Integer.valueOf`有时会从池中返回值,因此结果可能是"true". (19认同)
  • @fabian所以,从不真实*以合理有用或直观的方式*. (3认同)
  • @MarounMaroun嗯,对于答案中的代码,它绝对不会是真的.`new Integer(b)`总是创建一个对象,而`Integer.valueOf(b)`可能不会. (2认同)

llo*_*giq 7

我无法用javac 1.7.0_75编译(修复bool→boolean),也不能用javac 1.8.0_60编译.我没有JDK6,但我认为它也不应该在那里工作.也许它是早期的ecj不兼容性,正如Axel提示的那样,或者是javac的另一个次要版本中的错误.

无论如何,如果它有效,那是由于自动装箱.为了准备Java 8,这可能已经被削减了,因为流和自动装箱不能很好地混合.


Zho*_*gYu 5

根据JLS 7,它不应该编译.int可以与盒装数字类型进行比较,即字节,短,字符,整数,长,浮点,双精度.但就是这样.

如果比较介于int和之间Float,Float则首先将取消装箱,以便比较在float和之间int.做相反的事情没有任何意义 - 框int然后检查Integer(Float不少于)的身份.