foreach
tetap menggunakan iterators di bawah tenda. Ini benar-benar hanya gula sintaksis.
Pertimbangkan program berikut:
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) {
}
}
}
Mari kita kompilasi dengan javac Whatever.java
,
Dan baca bytecode dibongkar main()
, menggunakan 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
Kita dapat melihat bahwa foreach
kompilasi ke sebuah program yang:
- Buat iterator menggunakan
List.iterator()
- Jika
Iterator.hasNext()
: memanggil Iterator.next()
dan melanjutkan loop
Adapun "mengapa loop tidak berguna ini dioptimalkan dari kode yang dikompilasi? Kita dapat melihat bahwa itu tidak melakukan apa-apa dengan item daftar": baik, mungkin bagi Anda untuk kode iterable Anda sehingga .iterator()
memiliki efek samping , atau lebih yang .hasNext()
memiliki efek samping atau konsekuensi yang berarti.
Anda dapat dengan mudah membayangkan bahwa iterable yang mewakili permintaan yang dapat digulir dari database mungkin melakukan sesuatu yang dramatis .hasNext()
(seperti menghubungi database, atau menutup kursor karena Anda telah mencapai akhir set hasil).
Jadi, meskipun kita dapat membuktikan bahwa tidak ada yang terjadi dalam loop body ... itu lebih mahal (sulit?) Untuk membuktikan bahwa tidak ada yang berarti / konsekuensi yang terjadi ketika kita mengulanginya. Kompilator harus meninggalkan tubuh loop kosong ini dalam program.
Yang terbaik yang bisa kami harapkan adalah peringatan kompiler . Sungguh menarik bahwa javac -Xlint:all Whatever.java
tidak tidak memperingatkan kita tentang tubuh lingkaran kosong ini. IntelliJ IDEA melakukannya. Memang saya telah mengkonfigurasi IntelliJ untuk menggunakan Eclipse Compiler, tapi itu mungkin bukan alasan mengapa.