107

Java SE 6 と Java SE 7 の自動アンボックス動作の違いに注目しました。これら 2 つのバージョン間でのこの動作の変更に関するドキュメントが見つからないため、なぜそうなのか不思議に思っています。

簡単な例を次に示します。

Object[] objs = new Object[2];
objs[0] = new Integer(5);
int myInt = (int)objs[0];

これは、Java SE 7 の javac で正常にコンパイルされます。ただし、コンパイラに「-source 1.6」引数を指定すると、最後の行でエラーが発生します。

inconvertible types
found   : java.lang.Object
required: int

Java SE 6 をダウンロードして、ネイティブ バージョン 6 コンパイラでコンパイルしようとしました (-source オプションなし)。同意し、上記と同じエラーが発生します。

それで、何が得られますか?いくつかの実験から、Java 6 でのボックス化解除は、明らかに (コンパイル時に) ボックス化された型である値のみをボックス化解除できるようです。たとえば、これは両方のバージョンで機能します。

Integer[] objs = new Integer[2];
objs[0] = new Integer(5);
int myInt = (int)objs[0];

そのため、Java 6 と 7 の間で、ボックス化解除機能が強化され、(コンパイル時に) 値が適切なボックス化された型であることを知らなくても、オブジェクト型を一度にキャストしてボックス化解除できるようになりました。しかし、Java 7 が出たときに書かれた Java 言語仕様またはブログ投稿を読んでも、このことの変更は見られないので、変更とは何なのか、この「機能」は何と呼ばれているのか疑問に思っています。 ?

ただの好奇心: 変更により、「間違った」ボックス化解除をトリガーする可能性があります。

Object[] objs = new Float[2];
objs[0] = new Float(5);
int myInt = (int)objs[0];

これは正常にコンパイルされますが、実行時に ClassCastException が発生します。

これに関する参照はありますか?

4

2 に答える 2

93

セクション 5.5 Java 7 JLS のキャスト変換の言語が、Java 5/6 JLS の同じセクションと比較して更新されたようです。おそらく、許可されている変換を明確にするためです。

Java 7 JLS 言う

参照型の式は、ボックス化解除変換によって、エラーなしでプリミティブ型へのキャスト変換を受ける場合があります。

Java 5/6:

参照型の値は、ボックス化解除変換 (§5.1.8) によってプリミティブ型にキャストできます。

Java 7 JLS には、参照型からプリミティブへの許可された変換 (この表は Java 5/6 JLS には含まれていません) の表 (表 5.1) も含まれています。これにより、オブジェクトからプリミティブへのキャストが、ボックス化解除による縮小参照変換として明示的にリストされます。

理由はこのメールで説明されています:

結論:仕様の場合。(Object)(int) を許可します。(int)(Object) も許可する必要があります。

于 2013-04-20T13:32:19.763 に答える
35

あなたが正しいです; もっと簡単に言えば:

Object o = new Integer(1234);
int x = (int) o;

これは Java 7 では機能しますが、Java 6 以下ではコンパイル エラーが発生します。不思議なことに、この機能は目立って文書化されていません。たとえば、ここでは言及されていません。それが新機能なのかバグ修正なのか (それとも新しいバグなのか?) については議論の余地があります。関連する情報と議論を参照してください。コンセンサスは、元の仕様のあいまいさを指しているようです。これは、JSR 292 (動的型付け言語) の実装にとって重要であったため、7 で修正された Java 5/6 でのわずかに不正確な/一貫性のない実装につながりました。

Java オートボクシングには、いくつかの罠と驚きがあります。例えば

Object obj = new Integer(1234);
long x = (long)obj;

コンパイルされますが、実行時に ( で) 失敗ClassCastExceptionします。代わりに、これは機能します:

long x = (long)(int)obj;

于 2013-04-20T12:41:28.197 に答える