foreach
utilizza iteratori sotto il cofano stesso. È davvero solo zucchero sintattico.
Si consideri il seguente programma:
import java.util.List;
import java.util.ArrayList;
public class Whatever {
private final List<Integer> list = new ArrayList<>();
public void main() {
for(Integer i : list) {
}
}
}
Diamo compilare con javac Whatever.java
,
E leggere il bytecode smontato di main()
, utilizzando javap -c Whatever
:
public void main();
Code:
0: aload_0
1: getfield #4 // Field list:Ljava/util/List;
4: invokeinterface #5, 1 // InterfaceMethod java/util/List.iterator:()Ljava/util/Iterator;
9: astore_1
10: aload_1
11: invokeinterface #6, 1 // InterfaceMethod java/util/Iterator.hasNext:()Z
16: ifeq 32
19: aload_1
20: invokeinterface #7, 1 // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
25: checkcast #8 // class java/lang/Integer
28: astore_2
29: goto 10
32: return
possiamo vedere che foreach
compila fino a un programma che:
- Crea iteratore utilizzando
List.iterator()
- Se
Iterator.hasNext()
: invoca Iterator.next()
e continua ad anello
Per quanto riguarda "il motivo per cui non questo ciclo inutile ottenere ottimizzato fuori del codice compilato? possiamo vedere che non fa nulla con la voce dell'elenco ": beh, è possibile codificare il tuo iterable tale che .iterator()
ha effetti collaterali, o in modo che .hasNext()
ha effetti collaterali o conseguenze significative
Si può facilmente immaginare che un iterabile che rappresenta una query scorrevole da un database possa fare qualcosa di drammatico su .hasNext()
(come contattare il database o chiudere un cursore perché si è raggiunta la fine del set di risultati)
Quindi, anche anche se possiamo provare che non succede niente nel corpo del loop ... è più costoso (intrattabile?) dimostrare che non accade nulla di significativo/consequenziale quando iteriamo. Il compilatore deve lasciare questo corpo del ciclo vuoto nel programma
Il meglio che potessimo sperare sarebbe un compiler avviso.È interessante il fatto che javac -Xlint:all Whatever.java
non sia non avvisarci su questo corpo del ciclo vuoto. IntelliJ IDEA però. Devo ammettere che ho configurato IntelliJ per usare Eclipse Compiler, ma questo potrebbe non essere il motivo per cui.
credo che per ognuno utilizza l'iteratore –
possibili duplicati http://stackoverflow.com/questions/2113216/which-is-more-efficient-a-for-each-loop-or-an-iterator –