Estoy mirando un código antiguo de 2001 y encontré esta declaración:
else {
do {
int c = XMLDocumentFragmentScannerImpl.this.scanContent();
if (c == 60) {
XMLDocumentFragmentScannerImpl.this.fEntityScanner.scanChar();
XMLDocumentFragmentScannerImpl.this.setScannerState(1);
break label913;
}
Nunca había visto esto antes y descubrí roturas etiquetadas aquí:
http://docs.oracle.com/javase/tutorial/java/nutsandbolts/branch.html
¿No funciona esto esencialmente goto? ¿Es incluso una buena práctica usarlo? Me hace sentir incómodo.

label913definido?Respuestas:
No, no es como un goto, ya que no puede "ir" a otra parte del flujo de control.
Desde la página que vinculó:
Esto significa que solo puede romper los bucles que se estén ejecutando actualmente.
Considere este ejemplo:
first: for( int i = 0; i < 10; i++) { second: for(int j = 0; j < 5; j ++ ) { break xxx; } } third: for( int a = 0; a < 10; a++) { }Puede reemplazar
xxxconfirstosecond(para romper el bucle externo o interno), ya que ambos bucles se están ejecutando, cuando presiona labreakinstrucción, pero reemplazarxxxconthirdno se compilará.fuente
break first;, si lo usara , ¿el compilador volvería a subir a la línea inmediatamente despuésfirst:y ejecutaría esos bucles nuevamente?break first;sería romper (fin) el bucle de etiquetadofirst, es decir, que continuará conthird. Por otro ladocontinue first;, finalizaría la iteración actual defirsty se romperíasecondcon eso y continuaría con el siguiente valor deiinfirst.gotomás o menos en el mismo sentido que unaif-elsedeclaración. Los Goto son mucho más "flexibles" como en "ir a cualquier parte", por ejemplo, a una posición antes del bucle (de hecho, así es como los lenguajes antiguos solían implementar los bucles: "si no se cumple la condición, ve al inicio del cuerpo del bucle (de nuevo)") . He tenido que lidiar con ellos recientemente y créanme:gotoes un verdadero dolor de cabeza, mientras que las roturas etiquetadas no lo son.gotoen absoluto, incluso si C ++ lo admite. Casi siempre hay una mejor manera de resolver las cosas que te ahorrarán muchos dolores de cabeza más adelante. La tentación puede llegar ... ¡resiste!No es tan terrible
gotoporque solo envía el control al final de la declaración etiquetada (generalmente una construcción de bucle). Lo que lo hacegotodesagradable es que es una rama arbitraria a cualquier lugar, incluidas las etiquetas que se encuentran más arriba en la fuente del método, de modo que puede tener un comportamiento de bucle propio. La funcionalidad de rotura de etiquetas en Java no permite ese tipo de locura porque el control solo avanza.Solo lo usé una vez hace unos 12 años, en una situación en la que necesitaba romper con los bucles anidados, la alternativa más estructurada habría hecho pruebas más complicadas en los bucles. No recomendaría usarlo mucho, pero no lo marcaría como un olor automático a código incorrecto.
fuente
Siempre es posible reemplazarlo
breakcon un nuevo método.Considere la verificación de código para cualquier elemento común en dos listas:
List list1, list2; boolean foundCommonElement = false; for (Object el : list1) { if (list2.contains(el)) { foundCommonElement = true; break; } }Puedes reescribirlo así:
boolean haveCommonElement(List list1, List list2) { for (Object el : list1) { if (list2.contains(el)) { return true; } } return false; }Por supuesto, para buscar elementos comunes entre dos listas, es mejor usar el
list1.retainAll(new HashSet<>(list2))método para hacerloO(n)conO(n)memoria adicional, o ordenar ambas listas enO(n * log n)y luego encontrar elementos comunes enO(n).fuente
gotoes (potencialmente) dañino porque podría enviarle a muchos lugares; no es en absoluto evidente lo que se está logrando; La creación de una función de ayuda le da límites claros al siguiente tipo en cuanto a lo que está tratando de hacer y dónde lo va a hacer, y le da la oportunidad de nombrar esa parte de la funcionalidad. Mucho más claro de esta manera.break, nogoto. Claro, la refactorización que se muestra aquí es una buena idea en ambos casos. Pero etiquetadobreakno es tan poco moderado y propenso al código espaguetizado comogotoes.Antes de leer el resto de esta respuesta, lea Ir a la declaración considerada dañina . Si no quiere leerlo en su totalidad, aquí está lo que considero el punto clave:
O para reformular, el problema con
gotoes que el programa puede llegar en medio de un bloque de código, sin que el programador comprenda el estado del programa en ese punto. Las construcciones estándar orientadas a bloques están diseñadas para delinear claramente las transiciones de estado, un etiquetadobreakestá destinado a llevar el programa a un estado conocido específico (fuera del bloque etiquetado que lo contiene).En un programa imperativo del mundo real, el estado no está claramente delimitado por límites de bloque, por lo que es cuestionable si la etiqueta
breakes una buena idea. Si el bloque cambia de estado que es visible desde fuera del bloque, y hay varios puntos para salir del bloque, entonces una etiquetabreakes equivalente a la primitivagoto. La única diferencia es que, en lugar de la posibilidad de aterrizar en medio de un bloque con un estado indeterminado, comienzas un nuevo bloque con un estado indeterminado.Entonces, en general, consideraría una etiqueta
breakcomo peligrosa. En mi opinión, es una señal de que el bloque debe convertirse en una función, con acceso limitado al alcance adjunto.Sin embargo, este código de ejemplo fue claramente el producto de un generador de analizador (el OP comentó que era el código fuente de Xerces). Y los generadores de analizadores sintácticos (o generadores de código en general) a menudo se toman libertades con el código que generan, porque tienen un conocimiento perfecto del estado y los humanos no necesitan entenderlo.
fuente
breakes bastante útil en varias ocasiones. Por ejemplo, cuando busca algún valor que puede provenir de varias fuentes ordenadas. Estás probando uno por uno, y cuando se encuentra el primero, túbreak. Es un código más elegante queif / else if / else if / else if. (Al menos son menos líneas). Mover todo al contexto de un método puede no ser siempre práctico. Otro caso es, si está rompiendo condicionalmente desde unos pocos niveles anidados. En resumen, si no te gustabreak, no te gustareturnningún otro lugar excepto el final de un método.doywhileno existían y todos usaban enif(.. ) gototodas partes. Tenía la intención de alentar a los diseñadores de idiomas a agregar soporte para cosas comodoywhile. Lamentablemente, una vez que el tren comenzó a rodar, se convirtió en un tren de bombo publicitario impulsado por personas ignorantes que pusieron cosas comobreakbucles de "solo se ejecuta una vez" y lanzaron excepciones a quién sabe qué, para todos los casos (raros) quegotoes más limpio y menos dañino.Esto no es como una
gotodeclaración en la que se hace retroceder el control de flujo. Una etiqueta simplemente le muestra a usted (el programador) dónde ha ocurrido la ruptura. Además, el control de flujo se transfiere a la siguiente declaración después debreak.Sobre su uso, personalmente creo que no es de gran utilidad, ya que una vez que comienzas a escribir un código que vale miles de líneas, se vuelve insignificante. Pero de nuevo, dependería del caso de uso.
fuente
for(int i = 0; i < 1; i++) { do_something(); if(I_want_to_go_backwards) { i = 0; continue; } }.Una forma más limpia de expresar la intención podría ser, al menos en mi opinión, poner el fragmento de código que contiene el bucle en un método separado y simplemente
returnpartir de él.Por ejemplo, cambie esto:
someLabel: for (int j = 0; j < 5; j++) { // do something if ... break someLabel; }dentro de esto:
private void Foo() { for (int j = 0; j < 5; j++) { // do something if ... return; } }Esto también es más idiomático para los desarrolladores que dominan otros lenguajes que podrían funcionar con su código en el futuro (o en el futuro ).
fuente