¿Cuál es una función alternativa para la palabra clave goto en Java?
Dado que Java no tiene goto.
¿Cuál es una función alternativa para la palabra clave goto en Java?
Dado que Java no tiene goto.
Respuestas:
Puede usar una declaración BREAK etiquetada :
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;
}
}
}
Sin embargo, en un código diseñado correctamente, no debería necesitar la funcionalidad GOTO.
No hay ningún equivalente directo al goto
concepto en Java. Hay algunas construcciones que le permiten hacer algunas de las cosas que puede hacer con un clásico goto
.
break
y le continue
permiten saltar de un bloque en un bucle o instrucción de cambio.break <label>
permite saltar de una declaración compuesta arbitraria a cualquier nivel dentro de un método dado (o bloque inicializador).continue <label>
continuar con la siguiente iteración de un bucle externo desde un bucle interno.return
.Ninguna de estas construcciones de Java le permite ramificarse hacia atrás o hacia un punto en el código en el mismo nivel de anidamiento que la declaración actual. Todos saltan uno o más niveles de anidación (alcance) y todos (excepto continue
) saltan hacia abajo. Esta restricción ayuda a evitar el síndrome de goto "código espagueti" inherente al antiguo código 2 de BASIC, FORTRAN y COBOL .
1- La parte más cara de las excepciones es la creación real del objeto de excepción y su seguimiento de pila. Si realmente, realmente necesita utilizar el manejo de excepciones para el control de flujo "normal", puede preasignar / reutilizar el objeto de excepción o crear una clase de excepción personalizada que anule el fillInStackTrace()
método. La desventaja es que la excepciónprintStackTrace()
métodos de no le darán información útil ... en caso de que alguna vez necesite llamarlos.
2 - El síndrome del código espagueti generó el enfoque de programación estructurada , en el que limitaba el uso de las construcciones de lenguaje disponibles. Esto podría aplicarse a BASIC , Fortran y COBOL , pero requería cuidado y disciplina. Deshacerse de él por goto
completo fue una solución pragmáticamente mejor. Si lo guardas en un idioma, siempre habrá algún payaso que abusará de él.
Solo por diversión, aquí hay una implementación GOTO en Java.
Ejemplo:
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 }
Ejecutarlo:
$ java -cp bin:asm-3.1.jar GotoClassLoader GotoDemo 3 2 1 0 Hello World!
¿Tengo que añadir "no lo use"?
Math.random()
puede devolver 0. Debería ser> =
Si bien algunos comentaristas y votantes negativos argumentan que esto no es goto , el código de bytes generado a partir de las siguientes declaraciones de Java realmente sugiere que estas declaraciones realmente expresan la semántica de goto .
Específicamente, el do {...} while(true);
compiladores de Java optimizan ciclo del segundo ejemplo para no evaluar la condición del ciclo.
label: {
// do stuff
if (check) break label;
// do more stuff
}
En 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);
En bytecode:
2 iload_1 [check]
3 ifeq 9
6 goto 2 // Jumping backward
9 ..
continue label
es el salto hacia atrás
// do stuff
y // do more stuff
son las declaraciones de interés, continue label
"tiene el efecto" de saltar hacia atrás (debido a la while(true)
declaración, por supuesto). Sin embargo, no sabía que esta era una pregunta tan precisa ...
while(true)
compilador traduce el en una goto
operación de código de bytes. Como true
es un literal constante, el compilador puede hacer esta optimización y no tiene que evaluar nada. Entonces, mi ejemplo realmente es un goto, saltando hacia atrás ...
Si realmente desea algo como declaraciones goto, siempre puede intentar dividir a bloques con nombre.
Tienes que estar dentro del alcance del bloque para romper con la etiqueta:
namedBlock: {
if (j==2) {
// this will take you to the label above
break namedBlock;
}
}
No te daré un sermón sobre por qué deberías evitar los goto, supongo que ya sabes la respuesta a eso.
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 escribe:
Hay dos construcciones que le permiten hacer algunas de las cosas que puede hacer con un goto clásico.
Uno mas...
Matt Wolfe escribe:
La gente siempre habla de no usar nunca un goto, pero creo que hay un caso de uso del mundo real realmente bueno que es bastante conocido y usado. Es decir, asegurarse de ejecutar algún código antes de que una función regrese. Por lo general, su lanzamiento cerraduras o lo que no, pero en mi caso me encantaría poder saltar a un descanso justo antes del regreso para poder hacer la limpieza obligatoria requerida.
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
El bloque finalmente siempre se ejecuta cuando sale el bloque try. Esto asegura que el bloque finalmente se ejecute incluso si ocurre una excepción inesperada. Pero finalmente es útil para algo más que el manejo de excepciones: le permite al programador evitar que el código de limpieza se omita accidentalmente por un retorno, continuación o interrupción. Poner el código de limpieza en un bloque final siempre es una buena práctica, incluso cuando no se anticipan excepciones.
La pregunta tonta de la entrevista asociada con finalmente es: Si regresa de un bloque try {}, pero también tiene un retorno en su finalmente {}, ¿qué valor se devuelve?
return
en un finally
bloque es una mala idea. (E incluso si el conocimiento no es estrictamente necesario, me preocuparía un programador que no tuviera la curiosidad de averiguarlo ...)
Lo más fácil es:
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;
}
}
Pruebe el siguiente código. Esto funciona para mi.
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 no lo tiene goto
, porque hace que el código no esté estructurado y sea poco claro para leer. Sin embargo, puede utilizar break
y continue
como forma civilizada de goto sin sus problemas.
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");
Salida :
Before Break
After ahead
before: {
System.out.println("Continue");
continue before;
}
Esto dará como resultado un bucle infinito, ya que cada vez que continue before
se ejecuta la línea , el flujo de código comenzará de nuevobefore
.
goto
estuviera disponible en Java? Creo que ahí radica la cuestión más importante.