programacion - ¿Java reconoce los bucles infinitos?
manual de programacion android pdf (8)
Entonces mi pregunta es: ¿esto está en alguna parte en la especificación de Java?
El programa es legal Java según la especificación. El JLS (y el compilador de Java) reconocen que el método no puede regresar y, por lo tanto, no se requiere ninguna declaración de return
. De hecho, si agrega una declaración de return
después del bucle, el compilador de Java le daría un error de compilación porque la declaración de devolución sería un código inalcanzable.
y hay alguna situación donde este comportamiento pueda ser útil?
No lo creo, excepto posiblemente en pruebas unitarias poco claras.
De vez en cuando escribo métodos que nunca volverán (normalmente), pero poner el hilo actual en un bucle ocupado infinito ininterrumpible rara vez tiene sentido.
Dado el siguiente ejemplo de código:
public class WeirdStuff {
public static int doSomething() {
while(true);
}
public static void main(String[] args) {
doSomething();
}
}
Este es un programa Java válido, aunque el método doSomething () debería devolver un int pero nunca lo hace. Si lo ejecuta, terminará en un bucle infinito. Si coloca el argumento del ciclo while en una variable separada (por ejemplo, boolean bool = true), el compilador le indicará que devuelva un int en este método.
Entonces mi pregunta es: ¿esto está en alguna parte en la especificación de Java y hay alguna situación donde este comportamiento podría ser útil?
Algunas notas sobre declaraciones inalcanzables:
En las especificaciones de java2 , se puede encontrar la descripción de ''declaración inalcanzable''. Especialmente interesante es la siguiente oración:
Excepto por el tratamiento especial de while , do , y para las declaraciones cuya expresión de condición tiene el valor constante verdadero, los valores de las expresiones no se tienen en cuenta en el análisis de flujo.
Por lo tanto, obviamente no es posible salir de while (true);
Bucle infinito. Sin embargo, había dos opciones más: cambiar los valores almacenados en caché o piratear directamente en el archivo de clase o en el espacio de la memoria operativa JVM.
Citaré la Especificación del lenguaje Java , ya que es bastante claro al respecto:
Esta sección está dedicada a una explicación precisa de la palabra "accesible". La idea es que debe haber alguna ruta de ejecución posible desde el comienzo del constructor, el método, el inicializador de la instancia o el inicializador estático que contiene la declaración en la declaración misma. El análisis toma en cuenta la estructura de los enunciados. Excepto por el tratamiento especial de while, do, y para las declaraciones cuya expresión de condición tiene el valor constante verdadero , los valores de las expresiones no se tienen en cuenta en el análisis de flujo.
...
Una instrucción while se puede completar normalmente si al menos uno de los siguientes es verdadero:
- La instrucción while es alcanzable y la expresión de condición no es una expresión constante con valor verdadero.
- Hay una declaración de interrupción alcanzable que sale de la instrucción while.
...
Cualquier otra afirmación S en un bloque no vacío que no sea un bloque de conmutadores es alcanzable si la instrucción que precede a S puede completarse normalmente.
Y luego aplica las definiciones anteriores a this :
Si se declara que un método tiene un tipo de retorno, entonces cada declaración de retorno (§14.17) en su cuerpo debe tener una Expresión. Se produce un error en tiempo de compilación si el cuerpo del método puede completarse normalmente (§14.1).
En otras palabras, un método con un tipo de devolución debe regresar solo mediante el uso de una declaración de devolución que proporciona un retorno de valor; no está permitido "dejar caer el extremo de su cuerpo".
Tenga en cuenta que es posible que un método tenga un tipo de devolución declarado y, sin embargo, no contenga declaraciones de devolución. Aquí hay un ejemplo:
class DizzyDean { int pitch() { throw new RuntimeException("90 mph?!"); } }
Después de releer la pregunta ...
Java entiende mientras (verdadero); nunca puede completarse, no rastrea el siguiente código por completo.
boolean moo = true;
while (moo);
¿Esto es útil? Dudoso.
Es posible que esté implementando una interfaz general tal que, aunque el método pueda salir con un valor de retorno significativo, su implementación particular sea un bucle infinito útil (por ejemplo, un servidor de red) que nunca tenga una situación en la que debería salir, es decir, desencadenar cualquier acción que devuelva un valor significa.
Además, con respecto al código como boolean x = true; while (x);
boolean x = true; while (x);
, esto compilará dado un modificador final
en x
. No sé de improviso, pero me imagino que esta es la elección de Java de análisis de expresiones constantes razonables y directas (que debe definirse directamente ya que, debido a este rechazo de los programas que dependen de él, es parte de la definición del lenguaje).
La especificación Java define un concepto llamado declaraciones inalcanzables . No tiene permitido tener una declaración inalcanzable en su código (es un error de tiempo de compilación). Un while(true);
declaración hace las siguientes declaraciones inalcanzables por definición. Ni siquiera está permitido tener una declaración de return
después del while(true);
declaración en Java. Tenga en cuenta que si bien el problema de Detener es indecidible en un caso genérico, la definición de Declaración inalcanzable es más estricta que simplemente detenerse. Está decidiendo casos muy específicos donde un programa definitivamente no se detiene. El compilador teóricamente no puede detectar todos los bucles infinitos y las declaraciones inalcanzables, pero tiene que detectar casos específicos definidos en la especificación.
Sí, puede ver estos bucles "infinitos" en algunos subprocesos, por ejemplo, subprocesos de servidor que escuchan en un puerto determinado para los mensajes entrantes.
Si está preguntando si los bucles infinitos pueden ser útiles, la respuesta es sí. Hay muchas situaciones en las que desea que algo se ejecute para siempre, aunque el bucle generalmente terminará en algún momento.
En cuanto a su pregunta: "¿Puede Java reconocer cuándo un ciclo será infinito?" La respuesta es que es imposible que una computadora tenga un algoritmo para determinar si un programa se ejecutará para siempre o no. Lea sobre: Detener el problema
Leyendo un poco más, su pregunta también pregunta por qué la función doSomething () no se queja de que no devuelve un int.
Curiosamente, la siguiente fuente NO compila.
public class test {
public static int doSomething() {
//while(true);
boolean test=true;
while(test){
}
}
public static void main(String[] args) {
doSomething();
}
}
Esto me indica que, como sugiere la página wiki sobre el problema de detención, es imposible que exista un algoritmo para determinar si terminará cada problema, pero esto no significa que alguien no haya agregado el caso simple:
while(true);
a las especificaciones de java Mi ejemplo anterior es un poco más complicado, por lo que Java no puede recordarlo como un bucle infinito. Verdaderamente, este es un caso extraño, pero está ahí solo para hacer que las cosas se compilen. Quizás alguien pruebe otras combinaciones.
EDITAR: no es un problema con el código inalcanzable.
import java.util.*;
public class test {
public static int doSomething() {
//while(true);
while(true){
System.out.println("Hello");
}
}
public static void main(String[] args) {
doSomething();
}
}
Lo anterior funciona, entonces el tiempo (verdadero); no está siendo ignorado por el compilador como inalcanzable, de lo contrario arrojaría un error de tiempo de compilación.