foreach
i tak używa iteratorów pod maską. To naprawdę tylko cukier syntaktyczny.
Rozważ następujący program:
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) {
}
}
}
Załóżmy, skompilować go javac Whatever.java
,
i odczytać kodu bajtowego z demontażu main()
, używając 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
Widzimy, że foreach
kompiluje się do programu, który:
- Tworzy iterator za pomocą
List.iterator()
- If
Iterator.hasNext()
: wywołuje Iterator.next()
i kontynuuje pętlę
Jeśli chodzi o „dlaczego ta bezużyteczna pętla nie jest zoptymalizowana ze skompilowanego kodu? Widzimy, że nic nie robi z pozycją listy”: cóż, możliwe jest kodowanie iterowalnej .iterator()
strony z efektami ubocznymi , lub .hasNext()
ma to skutki uboczne lub znaczące konsekwencje.
Można łatwo wyobrazić sobie, że iterowalna reprezentacja przewijalnego zapytania z bazy danych może zrobić coś dramatycznego .hasNext()
( na przykład skontaktowanie się z bazą danych lub zamknięcie kursora, ponieważ osiągnąłeś koniec zestawu wyników).
Tak więc, nawet jeśli możemy udowodnić, że nic nie dzieje się w ciele pętli… droższym (trudnym?) Jest udowodnienie, że podczas iteracji nie dzieje się nic znaczącego / wynikowego. Kompilator musi pozostawić to puste ciało w programie.
Najlepsze, na co moglibyśmy oczekiwać, to ostrzeżenie kompilatora . To ciekawe, że javac -Xlint:all Whatever.java
ma nie ostrzegają nas o tym pustym ciele pętli. IntelliJ IDEA to robi. Wprawdzie skonfigurowałem IntelliJ do korzystania z kompilatora Eclipse, ale to nie może być powód.