Zašto u JDK izvornom kodu, beskonačne petlje uglavnom koriste for(;;) umesto while(true)?
Na Zhihu-ju sam video R-ov odgovor, stvarno osećam potrebu da podelim sa svim prisutnim javaer-ima, iskreno prodorno.
Prvo treba pitati da li jeste, pa zašto serija.
U JDK8u jdk projektu napravimo vrlo grubu pretragu:
mymbp:/Users/me/workspace/jdk8u/jdk/src
$ egrep -nr "for \\(\\s?;\\s?;" . | wc -l
369
mymbp:/Users/me/workspace/jdk8u/jdk/src
$ egrep -nr "while \\(true" . | wc -l
323Nema velike razlike.
Drugo, poreklo for (;😉 u Javi. Lično mišljenje je da oni koji vole ovu upotrebnu formu, korenito su pod uticajem pisanja u C jeziku. Ovi ljudi ne moraju biti prethodno navikli na pisanje C, već su mogli biti indirektno pod uticajem svojih C profesora, prethodnika.
U C jeziku, ako ne inkluduješ određena zaglavlja ili sam deklarišeš, nema ugrađenog _Bool / bool tipa, nema TRUE / FALSE / true / false tih _Bool / bool tipovih literalnih vrednosti.
Zato pretpostavimo da nismo inkludovali ona zaglavlja ili sami definisali gore navedene literale, najčešće while izjava bez napisanog uslova petlje u while (...) zagradama je ovakva:
while (1) {
/* ... */
}...ali ne svima se sviđa taj magični broj „1“.
I korišćenje for (;😉 za izražavanje nepisanog uslova petlje (odnosno ako se ne koristi break ili goto u telu petlje, ona je beskonačna petlja) je vrlo intuitivno——ovo je funkcionalnost same while izjave, i ne treba pisati bilo kakav magični broj. Zato se ova upotreba prenosi.
Uz to, u Javi sam sklon da pišem while (true), mada ne nevolim drugi da pišu for (;😉 u svojim projektima.
=====================================
Što se tiče Jave while (true) i for (;😉 koji je „efikasniji“. Za ovakva pitanja koja specifikacija ne reguliše, odgovor je „gledaj implementaciju“, jer implementacija samo treba da garantuje semantiku u skladu sa specifikacijom, a efikasnost nije u okviru specifikacije.
S gledišta Oracle/Sun JDK8u / OpenJDK8u implementacije, prvo pogledajmo kompajlirani rezultat javac za sledeće dve izjave:
public void foo() {
int i = 0;
while (true) { i++; }
}
/*
public void foo();
Code:
stack=1, locals=2, args_size=1
0: iconst_0
1: istore_1
2: iinc 1, 1
5: goto 2
*/i
public void bar() {
int i = 0;
for (;;) { i++; }
}```
/*
public void bar();
Code:
stack=1, locals=2, args_size=1
0: iconst_0
1: istore_1
2: iinc 1, 1
5: goto 2
*/Čak i ovakav kompajler koji gotovo ne radi nikakvo optimizacijo (samo uradio konstantno savijanje koje Java specifikacija zahteva, i vrlo malo drugih optimizacija), generisao je isti bajtkod za obe verzije. Kasnije interpretativno izvršenje, JIT kompajlacija itd. nije potrebno pričati, ulaz je isti, izlaz neće biti drugačiji.
Na kraju deljenja, Erge će reći nekoliko reči.
Možda u očima običnih ljudi, takva pitanja uopšte nemaju potrebu za traženjem istine, ali R veli je ozbiljno istražio, i dobio vrlo uverljiv odgovor.
Zato, sposobni ljudi imaju tri odlike.
Ubuduće možete slobodno i smelo pisati for(;;) while(true) ovakve smrtne petlje u kodu.
