以下(Java)代码是否合法?
class Test {
Object foo() {return "";}
boolean bar() {return foo() == true;}
}
它不会针对JDK 6编译,但在7+上似乎没问题。规格有变化吗?修复了一个错误吗?我一直在http://bugs.eclipse.org/bugs/show_bug.cgi?id=416950进行讨论,可以选择任何一种方式。
答案 0 :(得分:3)
关于引用相等的JLS在java 6和&之间没有变化。 7:
Chapter 15.21.3: Reference Equality Operators == and !=:
如果相等运算符的操作数都是引用 type或null类型,则操作是对象相等。
如果无法转换类型,则为编译时错误 通过转换转换将操作数转换为另一个的类型 (§5.5)。两个操作数的运行时值必然是 不相等的。
但是我发现Chapter 5.5: Casting Conversion有些变化。将布尔值转换为Object似乎在Java 7上被归类为装箱约定:
基本类型的表达式可以进行转换为a 引用类型没有错误,通过装箱转换。
⊡表示拳击转换
因此,由于原始true
可以转换为Object
,因此您的等式表达式可以在Java 7上被归类为引用相等,并且不会产生编译器错误
答案 1 :(得分:1)
事实证明,将基元与编译时类型“对象”的表达式进行比较是不合法的。 JLS 15.21明确禁止它:
可以使用相等运算符来比较两个操作数 convertible(§5.1.8)到数字类型,或两个boolean类型的操作数 或布尔值,或两个操作数,每个操作数都是引用类型或 null类型。所有其他情况都会导致编译时错误。
无论Java版本如何,Eclipse编译器都会标记错误。对于Java 7,Oracle JDK和OpenJDK都错误地允许代码进行编译。 Oracle和Open JDK中的bug在版本8中得到了更正。
总之,根据规范,这种不稳定的比较是非法的,并且只会针对特定语言版本目标子集编译某些编译器子集。不会在Java 4或8+上工作。其他答案中提到的转换转换仅适用于'='运算符,而不适用于'=='。 15.21.3仅适用于两个参考操作数。
答案 2 :(得分:0)
这是参考的字节代码
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
}
编译
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)
似乎是将返回的String
转换为未装箱的Boolean
。