Il classico goto
ha forme diverse con varie restrizioni su di esse. Be it return
, try{} catch{}
, throw
, break
o continue
. Sono tutti veramente goto
con alcuni bit aggiuntivi attorno ad esso.
Uno potrebbe refactificare continue
o break
in un altro stile di loop con return:
for (int i = 0; i <= max; i++) {
if(someTest) { continue; }
if(someOtherTest) { continue; }
doStuff;
}
Può essere scritto come:
for (int i = 0; i <= max; i++) {
func();
}
....
void func() {
if(someTest) { return; }
if(someOtherTest) { return; }
doStuff;
}
Quale è più facile da leggere? Bene, io tenderei a sostenere che il primo è perché il secondo perde il contesto del ciclo ... ma sono altrimenti uguali. È giusto che le persone tendano a vedere meno di continue
di quanto facciano con return
nel codice quotidiano.
Da Esercitazioni Java: dichiarazioni di diramazione break
e continue
quando utilizzato le etichette hanno un po 'più di energia di quanto la maggior parte delle persone capisca. Rende anche il codice un po 'più esplicito per quanto riguarda il quale loop viene interpretato dall'istruzione di controllo. Prendere in considerazione:
class ContinueWithLabelDemo {
public static void main(String[] args) {
String searchMe = "Look for a substring in me";
String substring = "sub";
boolean foundIt = false;
int max = searchMe.length() - substring.length();
test:
for (int i = 0; i <= max; i++) {
int n = substring.length();
int j = i;
int k = 0;
while (n-- != 0) {
if (searchMe.charAt(j++) != substring.charAt(k++)) {
continue test;
}
}
foundIt = true;
break test;
}
System.out.println(foundIt ? "Found it" : "Didn't find it");
}
}
Si noti che continue
e break
vengono utilizzati con un'etichetta che specifica il ciclo su cui continuano o interrompono (l'etichetta su break
non è necessaria perché è un solo livello, ma aiuta nella comprensione del codice).
Se lo volessi davvero, potresti rifattare questo codice in:
public class Demo {
public static void main(String[] args) {
String searchMe = "Look for a substring in me";
String substring = "sub";
boolean foundIt;
int max = searchMe.length() - substring.length();
foundIt = loop2(searchMe, substring, max);
System.out.println(foundIt ? "Found it" : "Didn't find it");
}
private static boolean loop2(String searchMe, String substring, int max) {
for (int i = 0; i <= max; i++) {
if (loop(searchMe, substring, i)) {
return true;
}
}
return false;
}
private static boolean loop(String searchMe, String substring, int j) {
int n = substring.length();
int k = 0;
while (n-- != 0) {
if (searchMe.charAt(j++) != substring.charAt(k++)) {
return false;
}
}
return true;
}
}
( Penso di aver fatto quel refactoring anche se ci sono sicuramente dei bit da brontolare su ) ... ma non sono proprio sicuro di cosa ti guadagna . E questi due metodi con rendimenti multipli attireranno l'ira dei "ritorni multipli sono una folla anti-pattern" (che hanno punti validi come continue
e break
sono folla anti-pattern - e nel caso precedente probabilmente anche l'ira più giustificata). Sì, questo potrebbe essere di nuovo scritto in un modo che fa uso di altri test che renderanno la freccia " un anti-pattern "la gente ti guarda divertente.
continue
è un'istruzione guardia in un ciclo. break
è un ritorno anticipato.
Perché qualcosa non viene usato molto non lo rende un modello anti. Significa solo che le persone non sono così familiari con esso.
Per inciso, goto
è che vede un po 'di ritorno in C # dove può essere utilizzato con restrizioni (nota che C # non ha un break
etichettato come fa Java e quindi senza passare attraverso i cerchi dei metodi di estrazione, questo è il modo di scrivere il codice).