为什么int-to-Object比较在Java7中有效,而在Java8中无效?
以下代码为什么int-to-Object比较在Java7中有效,而在Java8中无效?,java,Java,以下代码 private boolean compare(Object a, int b) { return a == b; } 在Java 7中编译,但在Java 8中会导致以下错误: 不可比较的类型:int和Object 请看以下问题: 似乎Java6和Java8不允许您比较int和Object,而Java7允许。有关于这方面的文件吗 我对这些决定的背景知识感兴趣。好像他们还没决定什么 我在JDK1.7.0.51中使用14.1.4。Java7将自动装箱应用于int privat
private boolean compare(Object a, int b) {
return a == b;
}
在Java 7中编译,但在Java 8中会导致以下错误:
不可比较的类型:int和Object
请看以下问题:
似乎Java6和Java8不允许您比较int
和Object
,而Java7允许。有关于这方面的文件吗
我对这些决定的背景知识感兴趣。好像他们还没决定什么
我在JDK1.7.0.51中使用14.1.4。Java7将自动装箱应用于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
编辑:
Oracle将此行为视为错误::Javac接受错误的二进制比较操作 相关JLS部分为15.21。Javac似乎将此视为 引用比较,但仅当 两个操作数都是引用类型。
…
JLS第15.21节中二进制比较的类型规则现在将 由javac正确执行。自从JDK5以来,javac已经接受了一些 具有类型错误的对象基元比较的程序 根据JLS 15.21。现在将正确地进行这些比较 标识为类型错误
我无法获得编译的示例(修复bool)→ boolean)使用javac1.7.0_75,也不使用javac1.8.0_60。我没有JDK6,但我认为它也不应该在那里工作。正如Axel所暗示的,这可能是早期ecj的不兼容,也可能是javac的另一个次要版本中的错误 在任何情况下,如果它工作,这是由于自动装箱。这可能是在为Java 8做准备时缩减的,因为流和自动装箱混合得不太好。提到了3种不同的
==
运算符:数值运算符、布尔运算符和引用运算符在您的示例中,==
运算符中没有一个,因此我们断定语句是非法的
让我们看看为什么在您的示例中不能应用==
:
- 不需要说明为什么它不相关
- 如果相等运算符的操作数都是引用类型或null类型,则该操作为对象相等 如果无法通过强制转换()将任一操作数的类型转换为另一个操作数的类型,则这是编译时错误。两个操作数的运行时值必然不相等。
- 如果相等运算符的操作数都是数字类型,或者一个是数字类型,另一个可转换为数字类型(),则对操作数()执行二进制数字升级
if (a == new Integer(b))
你期望结果是什么?该条件的计算结果永远不会为
true
,因此有理由认为这是一个在Java8中修复的bug。根据int
可与装箱数字类型进行比较,即字节、短字符、字符、整数、长字符、浮点、双精度。但仅此而已
如果比较是在
int
之间,并且说是Float
,那么Float
将首先解除绑定,这样比较是在Float
和int
之间进行的。用另一种方法绕过-boxint
,然后检查整数的标识(使用浮点数
)是没有意义的。错误是在eclipse中显示的(即使用ecj时)还是由JDK编译器显示的?我猜这是ecj中的一个错误……如果是这样的话,我会认为Java 7与Oracle的Java 7犯了一个错误,我得到了“不兼容的操作数类型:Object和int”。您是否提供了您在Java 7编译中观察到的确切代码?@andythonas我想这取决于1.7 jdk的具体版本。llogiq不能用JDK1.7.0_75编译,而wero可以用JDK1.7.0_71编译。也许他们在这些版本之间修复了一个bug?jdk 1.7.0上的编译失败,但是自动装箱是使用Integer.valueOf
完成的。由于Integer.valueOf
有时会从池中返回值,因此结果可能是true
@fabian所以,以合理有用或直观的方式永远不会为true。@Marounnaroun好吧,对于答案中的代码,它肯定永远不会为truenewinteger(b)
总是创建一个对象,而Integer.valueOf(b)
可能不会。正如其他评论者所说,这个答案是错误的。使用自动装箱可以很好地定义比较整数和对象。