17

通常、コンパイラはボクシングとアンボクシングを実行するコードを生成します。しかし、ボックス化された値が必要ない場合、コンパイラは何をしますか?(Oracle標準)コンパイラはそれを最適化するのに十分賢いですか?

この方法を見てください:

public static void requireInRange(int index, Object[] array) {
    if(index < 0 || index >= array.length)
        throw new IndexOutOfBoundsException();
}

関連する情報は。だけarray.lengthなので、たとえば配列の各値をボックス化することは無意味です。このコードのように:

int[] anArray = {3, 4, 2};
requireInRange(3, anArray);

コンパイラは実際に配列の各値をボックス化するためのコードを挿入しますか?

4

3 に答える 3

45

コードにオートボクシングはありません。実際、与えられた:

public static void requireInRange(int index, Object[] array) {
   ...
}

int[] anArray = {3, 4, 2};
requireInRange(3, anArray); // DOES NOT COMPILE!!!

はに自動intボックス化できますがInteger、 Javaは自動ボックス化されint[]ませInteger[]。これを行うためのライブラリ関数を作成することはできますが、言語はこの変換を容易にしません。

Arrays.asList(anIntArray)これは、実際には、たとえば「壊れている」ことに関する多くの混乱の原因です。なぜならList<Integer>、返されるのは、実際には1つの要素であるためList<int[]>です。


しかし、パフォーマンスはどうですか?

Java言語ガイド/オートボクシングからの引用:

科学計算やその他のパフォーマンスに敏感な数値コードに自動ボックス化とボックス化解除を使用することは適切ではありません。AnIntegerint;の代わりにはなりません。オートボクシングとアンボクシングは、プリミティブ型と参照型の区別を曖昧にしますが、それを排除するものではありません。

つまり、オートボクシングが発生するたびに、パフォーマンスは確実に少し影響を受けます。これらのタイプに組み込まれているキャッシングメカニズムなど、特定のものがこれを軽減するのに役立ちます。これが、次のような理由です。

    System.out.println(
        ((Integer) 0) == ((Integer) 0)
    );
    // true

    System.out.println(
        ((Integer) 10000) == ((Integer) 10000)
    );
    // false (implementation-specific)

ここで起こったことは、0自動的にボックス化された場合、実際には新しい Integerインスタンスは作成されないということです。パフォーマンスを向上させるために、特定の範囲の値が自動ボックス化の目的でキャッシュされます。10000ほとんどの実装ではおそらくこの範囲から外れますが、一部のJVM実装では、必要に応じてキャッシュ範囲を指定できます。


しかし、配列の長さを取得したいだけです!!!

requireInRangeあらゆるタイプのアレイでの作業を容易にする方法はたくさんあります。残念ながら、Javaのプリミティブの配列を操作することは、多くの場合、多くの繰り返しを意味します。これは、、、、などに個別にオーバーロードを提供することを意味しますint[]boolean[]byte[]Object[]

より簡潔なオプションはリフレクションを使用することですが、これには長所と短所があります。一般的に言って、リフレクションはほとんどのシナリオで推奨されるソリューションではありません。

java.lang.reflect.Arrayそうは言っても、任意の配列の長さを返すことができるメソッドがあります。タイプセーフではありません(ほとんどの反射メカニズムのように)。非配列を渡すとコンパイルされますが、実行時にスローされます。int getLength(Object array) staticIllegalArgumentException

関連する質問

于 2010-08-07T13:56:25.400 に答える
4

コンパイラは実際に配列の各値をボックス化するためのコードを挿入しますか?

int[]パラメータを受け取るメソッドにを渡すことができないため、コンパイラはコードを拒否しObject[]ます。

オートボクシングは個々のプリミティブ値に対してのみ発生し、配列全体に対しては発生しません。

于 2010-08-07T13:58:24.990 に答える
3

疑わしい場合は、コンパイラがコードを最適化しないと想定できます。通常、コードの文字通りの翻訳を行います。

さらに、疑問がある場合は、JVM が実行時にコードを最適化するのに非常に優れていると想定できます。それが問題であると疑う正当な理由 (プロファイラーなど) がない限り、違いはないと思います。

于 2010-08-07T15:26:22.407 に答える