6

以下の (Java) コードは合法ですか?

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

JDK 6 に対してはコンパイルされませんが、7 以降では問題ないようです。仕様変わった?バグは修正されましたか?私はhttp://bugs.eclipse.org/bugs/show_bug.cgi?id=416950で議論してきましたが、これについてはどちらの方法でもかまいません。

4

3 に答える 3

3

参照の等価性に関する JLS は Java 6 と 7 の間で変わりません:

第15.21.3章: 等価演算子 == および != の参照:

等価演算子のオペランドが両方とも参照型または null 型の場合、演算はオブジェクト等価です。

キャスト変換 (§5.5) によっていずれかのオペランドの型を他方の型に変換できない場合、コンパイル時エラーになります。2 つのオペランドの実行時の値は、必然的に等しくありません。

ただし、 Chapter 5.5: Casting Conversionにいくつかの変更があることに気付きました。ブール値を Object にキャストすることは、Java 7 のボクシング規則として分類されているようです。

プリミティブ型の式は、ボックス化変換によって、エラーなく参照型にキャスト変換される場合があります。

ここに画像の説明を入力

⊡はボクシング変換を意味します

したがって、プリミティブtrueは にキャストできるためObject、等価式は Java 7 で参照等価として分類でき、コンパイラ エラーは発生しません。

于 2013-09-11T02:13:44.273 に答える
1

結局のところ、プリミティブをコンパイル時の型「オブジェクト」の式と比較することは正当ではありません。JLS 15.21は明示的に禁止しています。

等値演算子は、数値型に変換可能な ( §5.1.8 ) 2 つのオペランド、boolean または Boolean 型の 2 つのオペランド、またはそれぞれ参照型または null 型の 2 つのオペランドを比較するために使用できます。それ以外の場合はすべて、コンパイル時エラーになります。

Eclipse コンパイラーは、Java のバージョンに関係なく、エラーにフラグを立てます。Java 7 の場合、Oracle JDK と OpenJDK の両方が誤ってコードのコンパイルを許可します。Oracle および Open JDK のこのバグは、バージョン 8 で修正されています。

要約すると、この不安定な比較は仕様によれば違法であり、言語バージョン ターゲットの特定のサブセットのコンパイラのサブセットでのみコンパイルされます。Java 4 または 8 以降では動作しません。他の回答で言及されているキャスト変換は、「==」ではなく「=」演算子にのみ適用されます。15.21.3は、2 つの参照オペランドにのみ適用されます。

于 2013-09-12T03:39:54.507 に答える
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です。

于 2013-09-11T02:12:42.937 に答える