forループで拡張されたJavaでは、ループされる式が一度だけ評価されると仮定しても安全ですか?

StackOverflow https://stackoverflow.com/questions/1618202

質問

Javaでは、for-eachループ。
genArray()と呼ばれる配列を生成するメソッドがある場合。

次のコードでは、 genArray()を呼び出すことにより、毎回配列が再生成されますか? または、Javaがメソッドを一度呼び出して、配列からコピーを保存しますか?

for (String s : genArray())
{
    //...
}

ありがとう

役に立ちましたか?

解決

拡張forステートメントについて、Java言語仕様書の記述:

  

拡張forステートメントには   フォーム:

EnhancedForStatement:
        for ( VariableModifiersopt Type Identifier: Expression) Statement
     

式には型が必要です    Iterable またはそれ以外の場合   配列型(§ 10.1)、またはコンパイル時   エラーが発生します。

     

宣言されたローカル変数のスコープ   のFormalParameter部分   拡張された for ステートメント(§ 14.14)は   含まれている声明

     

拡張された for の意味   文はへの翻訳によって与えられます   基本的な for ステートメント。

     

Expression のタイプが    Iterable のサブタイプ、次に I を   式のタイプ    iterator()。拡張された for ステートメントは同等です   の基本的な for ステートメントに   フォーム:

for (I #i = Expression.iterator(); #i.hasNext(); ) {

        VariableModifiersopt Type Identifier = #i.next();
   Statement
}
     

#i はコンパイラによって生成されたものです   任意のものとは異なる識別子   その他の識別子(コンパイラ生成   またはその他)スコープ内(§ 6.3)   が強化された時点で   ステートメントが発生します。

     

そうでなければ、式は必然的に   配列タイプ T [] があります。 L1 ... Lm   (おそらく空の)シーケンス   直前のラベル   拡張された for ステートメント。そうして   拡張forステートメントの意味   次の基本的な for によって与えられます   ステートメント:

T[] a = Expression;
L1: L2: ... Lm:
for (int i = 0; i < a.length; i++) {
        VariableModifiersopt Type Identifier = a[i];
        Statement
}
     

a および i がコンパイラによって生成される場所   任意のものとは異なる識別子   その他の識別子(コンパイラ生成   またはその他)   forステートメントが強化された場所   発生します。

したがって、あなたの場合、 genArray() Iterable のサブタイプではなく配列タイプを返すため、拡張された for ステートメント次の基本的な for ステートメントと同等です:

String[] a = genArray();
...
for (int i = 0; i < a.length; i++) {
    String s = a[i];
    // ...
}
したがって、

そして genArray()は一度だけ呼び出されます(ただし、現在受け入れられている答えは部分的に間違っています)。

他のヒント

JavaはgenArray()を1回呼び出し、反復子オブジェクトを取得し、それを複数回呼び出します。

一度だけ使用する必要があります-これを呼び出すのと同じです:

  String[] strings = genArray();
  for (String s : strings) {
  ...
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top