19

これらの 2 つの構造は同等ですか?

char[] arr = new char[5];
for (char x : arr) {
    // code goes here
}

に比べ:

char[] arr = new char[5];
for (int i = 0; i < arr.length; i++) {
    char x = arr[i];
    // code goes here
}

つまり、両方のループの本体にまったく同じコードを入れた場合 (そしてそれらがコンパイルされた場合)、それらはまったく同じように動作しますか?


完全な免責事項:これは別の質問に触発されたものです(Java:これら2つのコードは同じですか)。そこでの私の答えは答えではないことが判明しましたが、Java for-each の正確なセマンティクスには指摘が必要なニュアンスがあると感じています。

4

4 に答える 4

31

多くの場合、2 つの構造は互換性がありますが、100% 同等というわけではありません!!!

// code goes here証明は、2 つの構造の動作が異なるように定義することによって構築できます。そのようなループ本体の 1 つを次に示します。

arr = null;

したがって、現在比較しています。

char[] arr = new char[5];
for (char x : arr) {
    arr = null;
}

と:

char[] arr = new char[5];
for (int i = 0; i < arr.length; i++) {
    char x = arr[i];
    arr = null;
}

どちらのコードもコンパイルされますが、実行すると、最初のループは正常に終了し、2 番目のループはNullPointerException.

これは、それらが 100% 同等ではないことを意味します。2 つのコンストラクトの動作が異なるシナリオがあります。

このようなシナリオはめったに発生しない可能性がありますが、デバッグ時にこの事実を忘れてはなりません。


補足として、インデックスが必要な場合など、for-each コンストラクトがオプションではない場合があることに注意してください。ここでの重要な教訓は、それがオプションであっても、常に保証されているわけではないため、実際に同等の代替品であることを確認する必要があるということです。

同様に、for-each ループから始めて、後でインデックス付き for ループに切り替える必要があることに気付いた場合は、保証されていないため、セマンティクスを保持していることを確認してください

特に、_反復される配列/コレクションの参照への変更には注意してください_ (コンテンツへの変更はトリガーされる場合とトリガーされない場合がありますConcurrentModificationExceptionが、それは別の問題です)。

カスタム反復子を使用するコレクションを使用する場合、セマンティクスの保持を保証することもはるかに困難ですが、この例が示すように、単純な配列が含まれている場合でも、2 つの構造は異なります。

于 2010-03-11T05:14:00.653 に答える
2

それらはほぼ同等です。しかし、そうでないケースはほとんどありません。作るのが一番finalです。

final char[] arr = new char[5];   // Now arr cannot be set null as shown 
                                  // in above answer.

i--それでも、2 番目のループで実行できます。これらのありそうもないことをいくつか行わなければ、それらはほとんど同等です。

于 2010-03-11T05:42:27.683 に答える
1

最初のものはより読みやすく、より望ましいです。とにかくインデックスが必要な場合は、2番目のものをふっくらと使用してください。

于 2010-03-11T05:19:01.757 に答える