forループで拡張されたJavaでは、ループされる式が一度だけ評価されると仮定しても安全ですか?
質問
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) {
...