tutorial paneles example create java keyword goto

paneles - table swing java



Alternativa a una declaraciĆ³n goto en Java (11)

¿Cuál es una función alternativa para la palabra clave goto en Java?

Dado que Java no tiene un goto.


El 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; } }


Java no tiene goto , porque hace que el código no esté estructurado y no sea claro de leer. Sin embargo, puede usar break y continue como una forma civilizada de goto sin sus problemas.

Saltando hacia adelante usando break -

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

Saltando hacia atrás usando continue

before: { System.out.println("Continue"); continue before; }

Esto dará como resultado un ciclo infinito, ya que cada vez que la línea continue before se ejecute, el flujo de código comenzará nuevamente desde before .


Mientras que algunos comentaristas y downvoters argumentan que esto no se cumple, el bytecode generado a partir de las siguientes declaraciones de Java realmente sugiere que estas declaraciones realmente expresan goto semántica.

Específicamente, el do {...} while(true); loop en el segundo ejemplo está optimizado por los compiladores de Java para no evaluar la condición de bucle.

Saltando hacia adelante

label: { // do stuff if (check) break label; // do more stuff }

En bytecode:

2 iload_1 [check] 3 ifeq 6 // Jumping forward 6 ..

Saltando hacia atrás

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 ..


No hay ningún equivalente directo al concepto goto en Java. Hay algunas construcciones que le permiten hacer algunas de las cosas que puede hacer con un goto clásico.

  • Las sentencias break y continue permiten salirse de un bloque en una instrucción de bucle o conmutación.
  • Una instrucción etiquetada y break <label> permiten saltar de una declaración compuesta arbitraria a cualquier nivel dentro de un método determinado (o bloque de inicializador).
  • Si etiqueta una instrucción de bucle, puede continue <label> para continuar con la siguiente iteración de un bucle externo desde un bucle interno.
  • Lanzar y atrapar excepciones te permite (efectivamente) saltarte de muchos niveles de una llamada a un método. (Sin embargo, las excepciones son relativamente caras y se consideran una mala forma de hacer un flujo de control "ordinario" 1 ).
  • Y por supuesto, hay 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 anidación que la instrucción actual. Todos saltan uno o más niveles de anidación (alcance) y todos (aparte de continue ) saltan hacia abajo. Esta restricción ayuda a evitar el síndrome de "código de espagueti" inherente al viejo código BASIC, FORTRAN y COBOL 2 .

1- La parte más costosa de las excepciones es la creación real del objeto de excepción y su stacktrace. Si realmente necesita usar 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 método fillInStackTrace() . La desventaja es que los métodos printStackTrace() la excepción no le brindarán información útil ... si alguna vez necesita llamarlos.

2 - El síndrome de código spaghetti generó el enfoque de programación estructurada , donde usted limita el uso de los constructos de lenguaje disponibles. Esto podría aplicarse a BASIC , Fortran y COBOL , pero requirió cuidado y disciplina. Deshacerse de goto completo fue una solución pragmáticamente mejor. Si lo mantienes en un idioma, siempre hay algún payaso que lo abusará.


Podría 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.


Pruebe el código a continuación. 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++) {"


Si realmente quieres algo como declaraciones goto, siempre puedes intentar romper con bloques con nombre.

Tienes que estar dentro del alcance del bloque para romper la etiqueta:

namedBlock: { if (j==2) { // this will take you to the label above break namedBlock; } }

No te voy a dar una lección sobre por qué deberías evitar los ataques de goto. Supongo que ya sabes la respuesta a eso.


Solo por diversión, here hay una implementación de 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 }

Correrlo:

$ java -cp bin:asm-3.1.jar GotoClassLoader GotoDemo 3 2 1 0 Hello World!

¿Debo agregar "no lo uso"?


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 nunca usar un goto, pero creo que hay un caso de uso del mundo real que es bastante conocido y utilizado ... Es decir, asegurarse de ejecutar algún código antes de que regrese de una función. Por lo general, se libera. bloquea o no, pero en mi caso me encantaría poder saltar a un descanso justo antes del regreso, así puedo hacer la limpieza requerida obligatoria.

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 finally siempre se ejecuta cuando sale el bloque try. Esto asegura que el bloque finally se ejecuta incluso si ocurre una excepción inesperada. Pero finalmente es útil para algo más que el manejo de excepciones: permite que el programador evite que el código de limpieza sea anulado accidentalmente por un retorno, continuación o interrupción. Poner el código de limpieza en un bloque finally es siempre una buena práctica, incluso cuando no se prevén excepciones.

La pregunta tonta de la entrevista asociada con finalmente es: si regresas de un bloque try {}, pero también tienes un return en tu {} finalmente, ¿qué valor se devuelve?


Use un descanso etiquetado como alternativa a goto.


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); }