Qual è una funzione alternativa per la parola chiave goto in Java?
Poiché Java non ha un file goto.
Qual è una funzione alternativa per la parola chiave goto in Java?
Poiché Java non ha un file goto.
Risposte:
Puoi utilizzare un'istruzione BREAK etichettata :
search:
for (i = 0; i < arrayOfInts.length; i++) {
for (j = 0; j < arrayOfInts[i].length; j++) {
if (arrayOfInts[i][j] == searchfor) {
foundIt = true;
break search;
}
}
}
Tuttavia, in un codice progettato correttamente, non dovrebbe essere necessaria la funzionalità GOTO.
Non esiste alcun equivalente diretto al goto
concetto in Java. Ci sono alcuni costrutti che ti permettono di fare alcune delle cose che puoi fare con un classico goto
.
break
e continue
ti consentono di saltare fuori da un blocco in un ciclo o in un'istruzione switch.break <label>
consente di saltare da un'istruzione composta arbitraria a qualsiasi livello all'interno di un determinato metodo (o blocco di inizializzazione).continue <label>
continuare con l'iterazione successiva di un ciclo esterno da un ciclo interno.return
.Nessuno di questi costrutti Java consente di ramificarsi all'indietro o fino a un punto del codice allo stesso livello di nidificazione dell'istruzione corrente. Tutti saltano fuori da uno o più livelli di nidificazione (ambito) e tutti (a parte continue
) saltano verso il basso. Questa restrizione aiuta ad evitare la sindrome del "codice spaghetti" goto insita nei vecchi codici BASIC, FORTRAN e COBOL 2 .
1- La parte più costosa delle eccezioni è la creazione effettiva dell'oggetto eccezione e del suo stacktrace. Se hai davvero, davvero bisogno di usare la gestione delle eccezioni per il controllo del flusso "normale", puoi preallocare / riutilizzare l'oggetto eccezione o creare una classe di eccezione personalizzata che sovrascrive il fillInStackTrace()
metodo. Lo svantaggio è che i printStackTrace()
metodi dell'eccezione non ti daranno informazioni utili ... se dovessi mai aver bisogno di chiamarli.
2 - La sindrome del codice spaghetti ha generato l' approccio di programmazione strutturata , dove hai limitato l'uso dei costrutti linguistici disponibili. Questo potrebbe essere applicato a BASIC , Fortran e COBOL , ma richiedeva cura e disciplina. Liberarsi del goto
tutto era una soluzione pragmaticamente migliore. Se lo mantieni in una lingua, c'è sempre qualche clown che ne abusa.
Solo per divertimento, ecco un'implementazione GOTO in Java.
Esempio:
1 public class GotoDemo { 2 public static void main(String[] args) { 3 int i = 3; 4 System.out.println(i); 5 i = i - 1; 6 if (i >= 0) { 7 GotoFactory.getSharedInstance().getGoto().go(4); 8 } 9 10 try { 11 System.out.print("Hell"); 12 if (Math.random() > 0) throw new Exception(); 13 System.out.println("World!"); 14 } catch (Exception e) { 15 System.out.print("o "); 16 GotoFactory.getSharedInstance().getGoto().go(13); 17 } 18 } 19 }
Eseguendolo:
$ java -cp bin:asm-3.1.jar GotoClassLoader GotoDemo 3 2 1 0 Hello World!
Devo aggiungere "non usarlo!"?
Math.random()
può restituire 0. Dovrebbe essere> =
HellWorld!o World!
output e rimarrà sconcertato. #AllBugsAreFeatures
Mentre alcuni commentatori e downvoters sostengono che questo non è goto , il bytecode generato dalle istruzioni Java seguenti suggerisce davvero che queste istruzioni esprimono davvero la semantica goto .
In particolare, il do {...} while(true);
ciclo nel secondo esempio è ottimizzato dai compilatori Java per non valutare la condizione del ciclo.
label: {
// do stuff
if (check) break label;
// do more stuff
}
In bytecode:
2 iload_1 [check]
3 ifeq 6 // Jumping forward
6 ..
label: do {
// do stuff
if (check) continue label;
// do more stuff
break label;
} while(true);
In bytecode:
2 iload_1 [check]
3 ifeq 9
6 goto 2 // Jumping backward
9 ..
continue label
è il salto all'indietro
// do stuff
e // do more stuff
sono le dichiarazioni di interesse, continue label
"ha l'effetto" di saltare all'indietro (a causa della while(true)
dichiarazione ovviamente). Non sapevo che fosse una domanda così precisa, però ...
while(true)
è tradotto dal compilatore in un'operazione goto
bytecode. Poiché true
è una costante letterale, il compilatore può eseguire questa ottimizzazione e non deve valutare nulla. Quindi, il mio esempio è davvero un goto, che salta all'indietro ...
Se vuoi davvero qualcosa come le istruzioni goto, puoi sempre provare a spezzare i blocchi con nome.
Devi essere nell'ambito del blocco per rompere l'etichetta:
namedBlock: {
if (j==2) {
// this will take you to the label above
break namedBlock;
}
}
Non ti spiegherò perché dovresti evitare i goto - presumo che tu sappia già la risposta a questo.
public class TestLabel {
enum Label{LABEL1, LABEL2, LABEL3, LABEL4}
/**
* @param args
*/
public static void main(String[] args) {
Label label = Label.LABEL1;
while(true) {
switch(label){
case LABEL1:
print(label);
case LABEL2:
print(label);
label = Label.LABEL4;
continue;
case LABEL3:
print(label);
label = Label.LABEL1;
break;
case LABEL4:
print(label);
label = Label.LABEL3;
continue;
}
break;
}
}
public final static void print(Label label){
System.out.println(label);
}
StephenC scrive:
Ci sono due costrutti che ti permettono di fare alcune delle cose che puoi fare con un goto classico.
Ancora uno ...
Matt Wolfe scrive:
La gente parla sempre di non usare mai un goto, ma penso che ci sia un ottimo caso d'uso nel mondo reale che è abbastanza noto e usato .. Cioè, assicurandosi di eseguire del codice prima di un ritorno da una funzione .. Di solito il suo rilascio serrature o cosa no, ma nel mio caso mi piacerebbe poter saltare a una pausa proprio prima del ritorno in modo da poter fare la pulizia obbligatoria richiesta.
try {
// do stuff
return result; // or break, etc.
}
finally {
// clean up before actually returning, even though the order looks wrong.
}
http://docs.oracle.com/javase/tutorial/essential/exceptions/finally.html
Il blocco finalmente viene eseguito sempre quando il blocco try esce. Ciò garantisce che il blocco finalmente venga eseguito anche se si verifica un'eccezione imprevista. Ma alla fine è utile per qualcosa di più della semplice gestione delle eccezioni: consente al programmatore di evitare che il codice di pulizia venga ignorato accidentalmente da un ritorno, continua o interruzione. Mettere il codice di pulizia in un blocco finally è sempre una buona pratica, anche quando non sono previste eccezioni.
La stupida domanda dell'intervista associata a finalmente è: se torni da un blocco try {}, ma hai un ritorno anche nel tuo finalmente {}, quale valore viene restituito?
return
in un finally
blocco è una cattiva idea. (E anche se la conoscenza non fosse strettamente necessaria, sarei preoccupato da un programmatore che non ha avuto la curiosità di scoprirlo ...)
Il più semplice è:
int label = 0;
loop:while(true) {
switch(state) {
case 0:
// Some code
state = 5;
break;
case 2:
// Some code
state = 4;
break;
...
default:
break loop;
}
}
Prova il codice qui sotto. Per me funziona.
for (int iTaksa = 1; iTaksa <=8; iTaksa++) { // 'Count 8 Loop is 8 Taksa
strTaksaStringStar[iCountTaksa] = strTaksaStringCount[iTaksa];
LabelEndTaksa_Exit : {
if (iCountTaksa == 1) { //If count is 6 then next it's 2
iCountTaksa = 2;
break LabelEndTaksa_Exit;
}
if (iCountTaksa == 2) { //If count is 2 then next it's 3
iCountTaksa = 3;
break LabelEndTaksa_Exit;
}
if (iCountTaksa == 3) { //If count is 3 then next it's 4
iCountTaksa = 4;
break LabelEndTaksa_Exit;
}
if (iCountTaksa == 4) { //If count is 4 then next it's 7
iCountTaksa = 7;
break LabelEndTaksa_Exit;
}
if (iCountTaksa == 7) { //If count is 7 then next it's 5
iCountTaksa = 5;
break LabelEndTaksa_Exit;
}
if (iCountTaksa == 5) { //If count is 5 then next it's 8
iCountTaksa = 8;
break LabelEndTaksa_Exit;
}
if (iCountTaksa == 8) { //If count is 8 then next it's 6
iCountTaksa = 6;
break LabelEndTaksa_Exit;
}
if (iCountTaksa == 6) { //If count is 6 then loop 1 as 1 2 3 4 7 5 8 6 --> 1
iCountTaksa = 1;
break LabelEndTaksa_Exit;
}
} //LabelEndTaksa_Exit : {
} // "for (int iTaksa = 1; iTaksa <=8; iTaksa++) {"
Java non ce l'ha goto
, perché rende il codice non strutturato e poco chiaro da leggere. Tuttavia, puoi usare break
e continue
come forma civile di goto senza i suoi problemi.
ahead: {
System.out.println("Before break");
break ahead;
System.out.println("After Break"); // This won't execute
}
// After a line break ahead, the code flow starts from here, after the ahead block
System.out.println("After ahead");
Uscita :
Before Break
After ahead
before: {
System.out.println("Continue");
continue before;
}
Ciò risulterà in un ciclo infinito poiché ogni volta che continue before
viene eseguita la riga , il flusso di codice ricomincerà dabefore
.
goto
fosse disponibile in Java? Penso che qui risieda la questione più importante.