java - until - ¿Hay casos en los que se debe usar while/do-while en lugar de for?
java 8 do while (4)
Este es un largo debate entre mi maestro y yo. ¿Puede haber una situación en la que un bucle for
no pueda usarse en lugar de un ciclo while
/ do
- while? En otras palabras, ¿hay un caso específico donde un bucle for
no funcionará en lugar de un bucle while? es while
/ do
- while
de alguna manera es "distinto" de for
?
"Absolutamente"? Yo diría que no. Sin embargo, una prueba posterior al bucle aka do-while en Java requeriría una muy complicada condición "para". Lo que nos lleva de regreso al absoluto booleano: la condición debe evaluar verdadero o falso.
Entonces, aunque no puedo imaginar un caso en el que el compilador no pueda ser manipulado para realizar la lógica correcta, puedo ver en muy poco tiempo que cualquiera que mantenga su programa podría querer que lo dropeen (o tal vez piense que ya lo hizo).
En una nota relacionada, no hay nada que puedas hacer en Java que no se pueda hacer en lenguaje de máquina. Pero hay muchas y muchas buenas razones para no usar el lenguaje de máquina. La mayoría de ellos se aplican por igual cuando intentas poner "lindo" escribiendo tu código. Todo es diversión y juegos hasta que hable por teléfono con un cliente iracundo en 0300, o su jefe, o ambos.
Las otras respuestas ya han cubierto la equivalencia entre un ciclo while y un ciclo for
. Es decir,
while(<expr>) {
<body>
}
es equivalente a
for(;<expr>;) {
}
Tenga en cuenta que se puede hacer una reducción similar con un ciclo do
- while. Cualquier bucle do
- while
do {
<body>
} while(<expr>);
es funcionalmente equivalente a
for (boolean firstIter = true; firstIter || <expr>; firstIter = false) {
<body>
}
No, no hay tal situación. Cada bucle do
- while se puede escribir en términos de while
-loop (ejecutando el cuerpo una vez antes del bucle) y viceversa. A su vez, cada while
-loop
while (X) {
...
}
Se puede escribir como
for (; X;) {
...
}
es decir, omitimos una inicialización y una declaración de incremento. También podemos convertir desde a for
atrás colocando correctamente la inicialización y el incremento.
En resumen, siempre es posible convertir de una variante de bucle a cualquiera de las otras dos. for
-loops solo le da la ventaja de poder limitar el alcance de una variable de control de bucle y hacer cualquier incremento en la parte superior. No hace falta decir que, en muchos casos, una variante de bucle particular tiene mucho más sentido que otras; cada uno tiene sus casos de uso específicos.
También tenga en cuenta que la diversión no solo termina con bucles: también es posible convertir cada bucle en una función recursiva y viceversa (aunque en la práctica podría haber limitaciones a esto, por ejemplo, un bucle que funcionó bien podría, cuando se convierte a una función recursiva, produce un error de desbordamiento de pila).
[I] s
while
/do
-while
de alguna manera es "distinto" defor
?
No lo es. Por ejemplo, el bytecode de los siguientes dos fragmentos es idéntico:
int x = 0;
while (x < 10) {
x++;
}
y
int x = 0;
for (; x < 10;) { // or: for (; x < 10; x++) {}
x++;
}
ambos se convierten en:
0: iconst_0
1: istore_1
2: goto 8
5: iinc 1, 1
8: iload_1
9: bipush 10
11: if_icmplt 5
14: return
Hubo comentarios en los comentarios sobre for-each bucles y que podrían ser intrínsecamente diferentes de los otros tipos de bucle. Esto no es absolutamente cierto; for
cada uno de los bucles es un azúcar sintáctico puro alrededor de los iteradores (o en forma de bucle sobre las matrices). Cada uno for
cada bucle también se puede convertir a cada uno de los otros tipos de bucle. Aquí hay un ejemplo:
for (String s : l) { // l is a list of strings
System.out.println(s);
}
y
String s;
Iterator<String> iter = l.iterator(); // l is a list of strings
while (iter.hasNext()) {
s = iter.next();
System.out.println(s);
}
ambos se convierten en:
24: invokeinterface #33, 1 // InterfaceMethod java/util/List.iterator:()Ljava/util/Iterator;
29: astore_3
30: goto 50
33: aload_3
34: invokeinterface #39, 1 // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
39: checkcast #19 // class java/lang/String
42: astore_2
43: getstatic #45 // Field java/lang/System.out:Ljava/io/PrintStream;
46: aload_2
47: invokevirtual #51 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
50: aload_3
51: invokeinterface #57, 1 // InterfaceMethod java/util/Iterator.hasNext:()Z
56: ifne 33
No, siempre puede reescribir un bucle for como un bucle while y cualquier otro mirar como un bucle for.
<init>
while (condition) {
...
<increment>
}
es equivalente a:
for (<init>; <condition>; <increment>) {
...
}