2009-10-24 7 views
8

En Java, une boucle for-each. Si j'ai une méthode qui génère un tableau, appelé .Dans une java améliorée pour la boucle, est-il sûr de supposer que l'expression à boucler ne sera évaluée qu'une seule fois?

Dans le code suivant, le tableau sera-t-il à chaque fois généré à nouveau en appelant genArray()? Ou Java appellera-t-il une fois la méthode et stockera-t-il une copie du tableau?

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

Merci

+3

Bien sûr, la façon la plus facile de savoir est de tester cela ... Un simple System.out.println() dans genArray() suffit! – PhiLho

+0

duplication possible de [Java foreach efficiency] (http://stackoverflow.com/questions/904582/java-foreach-efficiency) –

Répondre

23

À propos the enhanced for statement, le langage Java Spécifications écrit:

La version améliorée de déclaration a la forme :

EnhancedForStatement: 
     for (VariableModifiersopt Type Identifier: Expression) Statement 

L'expression doit avoir le type Iterable ou bien il doit être de type tableau (§10.1), ou une erreur de compilation se produit.

La portée d'une variable locale déclarée dans la partie FormalParameter d'une déclaration améliorée for (§14.14) est la déclaration contenue

La signification de la déclaration améliorée for est donnée par la traduction en une instruction de base for.

Si le type de Expression est un sous-type de Iterable, puis laissez I être le type de l'expression Expression.iterator(). Le renforcement de déclaration for est équivalente à une déclaration for de base de la forme :

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

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

Lorsque #i est un identificateur de compilateur généré qui est distincte de toute autres identificateurs (généré par le compilateur ou autrement) qui sont dans la portée (§6.3) au point où l'instruction améliorée pour se produit.

Dans le cas contraire, l'expression nécessairement a un type tableau, T[].Laisser L1 ... Lm être la séquence (éventuellement vide) des étiquettes précédant immédiatement l'instruction améliorée for. Alors le sens de l'amélioration de la déclaration est donnée par l'instruction de base for suivante:

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

un et i sont des identifiants de compilateur généré qui sont distincts de tout autres identifiants ( généré par le compilateur ou autre) qui sont dans la portée au point où se produit l'instruction améliorée pour l'instruction .

Donc, dans votre cas, genArray() ne retourne pas un sous-type de Iterable mais un type de tableau, de sorte que votre déclaration for améliorée est équivalente à l'instruction for de base suivante:

String[] a = genArray(); 
... 
for (int i = 0; i < a.length; i++) { 
    String s = a[i]; 
    // ... 
} 

Et genArray() sera donc être appelé qu'une seule fois (mais la réponse actuellement acceptée est partiellement erronée).

5

Java appellera genArray() une fois, obtenir l'objet iterator, et appeler que plusieurs fois.

+5

Cette réponse est partiellement ** incorrecte **. Oui, Java appellera 'genArray()' une seule fois mais, non, 'java.lang.Array' n'est pas un sous-type de' Iterable' donc Java n'aura pas d'objet itérateur. –

5

Il doit seulement se habituer une fois - c'est la même chose que d'appeler ceci:

String[] strings = genArray(); 
    for (String s : strings) { 
    ...