Java 将对象和原语与'==';操作人员

Java 将对象和原语与'==';操作人员,java,operators,autoboxing,jls,Java,Operators,Autoboxing,Jls,以下(Java)代码合法吗 class Test { Object foo() {return "";} boolean bar() {return foo() == true;} } 它不会针对JDK 6编译,但在7+上似乎可以。规格改变了吗?一个bug被修复了吗?我已经在上讨论过了,在这个问题上我可以选择任何一种方式。这是字节码供参考 class Test { Test(); Code: 0: aload_0 1: invokespecial

以下(Java)代码合法吗

class Test {
  Object foo() {return "";}
  boolean bar() {return foo() == true;}
}

它不会针对JDK 6编译,但在7+上似乎可以。规格改变了吗?一个bug被修复了吗?我已经在上讨论过了,在这个问题上我可以选择任何一种方式。

这是字节码供参考

class Test {
  Test();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":
       4: return

  java.lang.Object foo();
    Code:
       0: ldc           #2                  // String
       2: areturn

  boolean bar();
    Code:
       0: aload_0
       1: invokevirtual #3                  // Method foo:()Ljava/lang/Object;
       4: iconst_1
       5: invokestatic  #4                  // Method java/lang/Boolean.valueOf:
       8: if_acmpne     15
      11: iconst_1
      12: goto          16
      15: iconst_0
      16: ireturn
}

它似乎正在将返回的
字符串
转换为一个未装箱的
布尔值。

JLS关于引用相等性在java 6和java 7之间没有变化:

:

如果相等运算符的操作数都是引用 类型或空类型,则操作为对象相等

如果无法转换类型,则为编译时错误 通过强制转换将一个操作数转换为另一个操作数的类型 (§5.5). 两个操作数的运行时值必须是 不平等

然而,我注意到一些变化。将布尔值强制转换为对象似乎被归类为Java 7上的装箱约定:

基元类型的表达式可以进行强制转换为 通过装箱转换,引用类型无错误

⊡ 表示拳击转换

因此,由于原语
true
可以强制转换为
对象
,因此您的等式表达式可以在Java 7上归类为引用等式,并且不会产生编译器错误

,因为事实证明,将原语与编译时类型为“Object”的表达式进行比较是不合法的。明确禁止:

相等运算符可用于比较两个相同的操作数 可转换()为数值类型,或两个布尔类型的操作数 或布尔值,或两个操作数,每个操作数都是引用类型或 空类型。所有其他情况都会导致编译时错误

Eclipse编译器会标记错误,而不管Java版本如何。对于Java7,OracleJDK和OpenJDK都错误地允许编译代码。Oracle和Open JDK中的这一点在版本8中得到了纠正

总之,根据规范,这种不可靠的比较是非法的,并且只会在编译器的某些子集上编译语言版本目标的特定子集。不会在Java4或8+上工作。其他答案中提到的强制转换仅适用于“=”运算符,而不适用于“==”。仅适用于两个引用操作数。

检查上一篇文章,
java version "1.7.0_25"
Java(TM) SE Runtime Environment (build 1.7.0_25-b17)
Java HotSpot(TM) 64-Bit Server VM (build 23.25-b01, mixed mode)