Question

Is the below (Java) code legal?

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

It won't compile against JDK 6 but seems fine on 7+. Did the spec change? Was a bug fixed? I've been discussing at http://bugs.eclipse.org/bugs/show_bug.cgi?id=416950 and could go either way on this one.

Was it helpful?

Solution 2

As it turns out, it is not legal to compare a primitive with an expression of compile-time type 'Object'. JLS 15.21 expressly forbids it:

The equality operators may be used to compare two operands that are convertible (§5.1.8) to numeric type, or two operands of type boolean or Boolean, or two operands that are each of either reference type or the null type. All other cases result in a compile-time error.

The Eclipse compiler flags the error regardless of Java version. For Java 7, both Oracle JDK and OpenJDK erroneously allow the code to compile. This bug in Oracle and Open JDKs is corrected in version 8.

In summary, this wonky comparison is illegal according to the spec and will only compile on some subset of compilers for a particular subset of language version targets. Won't ever work on Java 4- or 8+. The casting conversions referred to in other answers apply only to the '=' operator, not to '=='. 15.21.3 applies only to two reference operands.

OTHER TIPS

JLS about reference equality doesn't change between java 6 & 7:

Chapter 15.21.3: Reference Equality Operators == and != :

If the operands of an equality operator are both of either reference type or the null type, then the operation is object equality.

It is a compile-time error if it is impossible to convert the type of either operand to the type of the other by a casting conversion (§5.5). The run-time values of the two operands would necessarily be unequal.

However I noticed some change on Chapter 5.5: Casting Conversion. Casting boolean to Object appears to be classified as boxing convention on Java 7:

An expression of a primitive type may undergo casting conversion to a reference type without error, by boxing conversion.

enter image description here

⊡ signifies boxing conversion

Hence since the primitive true can be casted to Object, your equality expression can be classified as reference equality on Java 7, and doesn't yield compiler error

Here's the byte code for reference

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
}

Compiled with

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)

It seems to be converting the returned String into a Boolean that gets unboxed.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top