web-dev-qa-db-ja.com

Java 6 vs Java 7

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言語仕様、または当時書かれたブログ投稿Java 7が出てきて、このことを変更するので、変更とは何か、この「機能」は何と呼ばれているのでしょうか?

好奇心:変更のため、「間違った」ボックス化解除をトリガーすることができます。

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

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

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

107
Morty

セクション5.5 Java 7 JLS のキャスト変換)の言語は Java 5/6 JLS 、おそらく許可される変換を明確にするため。

Java 7 JLSによると

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

Java 5/6:

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

Java 7 JLSには、参照タイプからの許可された変換のテーブル(表5.1)も含まれています(このテーブルはJava 5/6 JLSには含まれません)プリミティブへ:これは、オブジェクト化からプリミティブへのキャストを、ボックス化解除を伴う絞り込み参照変換として明示的にリストします。

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

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

92
Mark Rotteveel

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

_Object o = new Integer(1234);
int x = (int) o;
_

これはJava 7で動作しますが、Java 6以下ではコンパイルエラーが発生します。奇妙なことに、この機能はあまり文書化されていません。 here 。新しい機能かバグ修正(または新しいバグ?)かどうかは議論の余地があります。いくつかの 関連情報と議論 を参照してください。 曖昧さ 元の仕様では、Java 5/6、JSRの実装に不可欠だったため、7で修正された)でわずかに不正確/一貫性のない実装に至りました。 292(動的に型指定された言語)。

Javaのオートボクシングには、いくつかのトラップとサプライズがあります。例えば

_Object obj = new Integer(1234);
long x = (long)obj;
_

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

long x = (long)(int)obj;

35
leonbloy