java - sentencia - Punto y coma al final de la declaración ''if''
switch en java netbeans ejemplos (16)
¿Hay alguna situación en la que esto sea útil?
¿Útil? Como en "hace que su código sea más limpio, más rápido, más fácil de mantener"? De ningún modo. Probablemente este sea un código pobre y confuso .
Pero no es necesariamente benigno . Dicha declaración puede realizar acciones y / o alterar el estado debido a métodos que causan efectos secundarios, y opcionalmente evaluar esos métodos debido al cortocircuito de los operadores .
if( a() && b() );
Aquí, a()
o b()
puede hacer algo, y b()
solo se ejecutará si a()
es verdadero.
En cuanto a por qué , creo que la respuesta es simplemente que sería peor desviarse del comportamiento definido y esperado (por ejemplo, declaraciones como while(reader.read());
) que la alternativa de los desarrolladores que escriben código incorrecto.
Escribir código incorrecto siempre es posible. Y solo para reiterar, este sería un código incorrecto en casi cualquier caso.
Hoy, después de media hora de búsqueda de un error, descubrí que es posible poner un punto y coma después de una instrucción if en lugar de código, así:
if(a == b);
// Do stuff
Lo que básicamente significa que las cosas se harán si a es igual a b o no, y la declaración if no tiene ningún sentido. ¿Por qué Java no me da un error? ¿Hay alguna situación en la que esto sea útil?
¿Por que sucede?
La especificación del lenguaje Java dice que:
La declaración vacía
Una declaración vacía no hace nada.
EmptyStatement: ;
La ejecución de una declaración vacía siempre se completa normalmente
Básicamente, significa que desea ejecutar una declaración vacía si a == b
if(a == b);
¿Qué deberías hacer?
Hay dos soluciones principales a este problema:
Puede evitar problemas con instrucciones vacías utilizando el formateador de código y las cosas que lo rodean
if
tiene{
y}
. Al hacer esto, su declaración vacía será mucho más legible.if(a == b){ ; }
También puede verificar las herramientas utilizadas para el análisis de código estático, como:
Pueden resaltar instantáneamente problemas como este.
Yo recomendaría combinar ambas soluciones.
¿Por qué? Es porque es más fácil para los escritores de compilación. No es necesario hacer un caso especial para comprobar los puntos y coma después de if(cond)
y tiene un uso adicional de permitir
if (cond && maybeFunc())
;// Code here I want to ignore
Aunque en realidad es una idea terrible permitir esto. Simplemente es más fácil permitir y luego agregar una caja para verificar esto.
Algunas definiciones de los jls explican esto (capítulo 14):
Los bloques son declaraciones
Como se indica here , un Block
es un StatementWithoutTrailingSubstatement
, que a su vez es un StatementNoShortIf
, que es un Statement
. Por lo tanto, donde sea que se requiera alguno de estos, podemos insertar un Block
.
La cláusula if
Aunque este es también el caso de for
y while
-loops, usaré if
-statements. Estas reglas son más o menos lo mismo. La descripción sintáctica de if-statements
se puede encontrar here .
IfThenStatement:
if ( Expression ) Statement
IfThenElseStatement:
if ( Expression ) StatementNoShortIf else Statement
IfThenElseStatementNoShortIf:
if ( Expression ) StatementNoShortIf else StatementNoShortIf
Entonces podemos usar nuestro bloque aquí.
Pero, ¿por qué funciona? ?
;
se define como el EmptyStatement
( link ), que también es un StatementNoShortIf
. Por lo tanto, en las partes condicionales de código, como if-statement
y loops, podemos reemplazar un Block
con un EmptyStatement
, si se requiere un StatementNoShortIf
o Statement
.
Por if(Expression)EmptyStatement
tanto, if(Expression)EmptyStatement
funciona.
¿Por qué esto no da un error?
Bastante simple: Java da un error si encuentra una sintaxis inválida. Pero if(Expression)EmptyStatement
es una sintaxis perfectamente válida. En cambio, javac
da una advertencia si se lanza con los parámetros adecuados. La lista completa de advertencias que se pueden deshabilitar enumera el nombre de advertencia empty
para este propósito. Entonces la compilación con -Xlint:all
o -Xlint:empty
generará una advertencia sobre esto.
Su IDE debe tener una opción para habilitar este tipo de advertencia también. Para eclipse, vea la respuesta de @nullptr . En IntelliJ, puede presionar Ctrl + Shift + A
, ingresar empty body
en el campo de búsqueda y habilitar la advertencia (marcada en la imagen)
¿Para qué se usa esto?
Para ser honesto, no hay mucho uso desde un punto de vista minimalista. Usualmente hay una manera de hacer las cosas sin un comando de "no hacer nada". Es más bien una cuestión de preferencias personales, si prefieres usar
if( a() && b() );
o
if( a() ) b();
y lo mismo se aplicaría a otros casos, en los que se usa EmptyStatement
. Un punto importante a considerar sobre este tema es la legibilidad del código. Hay ocasiones en las que el código se vuelve más legible al usar el no-op. Por otro lado, hay casos en los que el código se vuelve bastante más difícil de comprender con EmptyStatement
; el ejemplo anterior contaría con el IMO posterior.
Es un viejo residuo de los días en que había más azúcar sintáctico para diferenciar las expresiones de los enunciados.
Básicamente, la coma se usó como el separador de elementos de la lista, por lo que el punto y coma se usó como el separador de "lista de declaraciones". La desventaja está en el manejo de elementos nulos en listas, y declaraciones nulas en bloques.
En una lista de elementos, Java usa la palabra clave explícita null
, pero una "declaración nula" es solo una línea vacía. Permitir la existencia de una línea vacía es un remanente de la tradición heredada de C.
¿Por que hacerlo? Especialmente con una instrucción if
cuando sabe que no se están ejecutando sentencias: debido a que algunas sentencias if tienen efectos secundarios:
int c;
if ((c = in.read()) != -1);
Sí, no es el mejor ejemplo, pero básicamente dice leer un byte de la transmisión y no hacer nada. Puede ser útil en algunos casos de esquina, pero incluso si este ejemplo no es el mejor, ilustra la intención. Queremos sentir los efectos secundarios de la expresión sin ejecutar accidentalmente ninguna declaración.
Estoy de acuerdo contigo, no hay un propósito útil para un ser humano. Sospecho que está ahí porque simplifica la definición del lenguaje; significa que lo que viene después de un if
es lo mismo que lo que viene después de un while
, por ejemplo.
Java permite un bloque vacío en cualquier lugar donde se permita un bloque de instrucción. Estoy seguro de que hacer de esto una regla general para todos los bloques simplifica el compilador.
Estoy de acuerdo en que esto es principalmente la causa de errores que son espectacularmente difíciles de encontrar. Siempre utilizo llaves alrededor de los bloques, incluso cuando hay una sola declaración, pero Java te permite hacer un bloque con llaves en cualquier punto, por lo que el uso de llaves no puede salvarte de este destino. Por ejemplo, una vez perdí 4 horas tratando de encontrar algo como esto:
while (condition);
{
statement;
statement;
}
El punto y coma al final de la primera línea era un error tipográfico, haciendo accidentalmente el bloque de declaración para el ciclo while vacío. Como la sintaxis es válida, el programa se compiló y funcionó bien, pero no de la manera que yo quería. Fue realmente difícil de encontrar.
Puedo pensar en una situación en la que es muy bueno que se te permita tener bloques vacíos, y esto es algo como esto:
if (condition1) {
do_action_1();
}
else if (condition2) {
//nothing really to do in this case
}
else if (condition3) {
do_action2();
}
else {
do_action3();
}
En el ejemplo anterior, desea poder separar varias condiciones. Recuerde que esas condiciones pueden superponerse, por lo que no siempre es posible reorganizar el orden. Si una de las condiciones realmente no necesita hacer nada, entonces es bueno que Java te permita tener un bloque vacío. De lo contrario, el idioma necesitaría algún tipo de método "noop" para usar cuando realmente no desea hacer nada.
Yo personalmente preferiría la declaración explícita de "noop", pero no es así como se define Java.
Mientras trabajaba en una asignación de programación para la clase donde estoy trabajando con una grilla de doodads N por N y comparando las características de una doodad aleatoria con las anteriores, inferiores, izquierda y derecha, encontré un buen uso de esto para evitar declaraciones anidadas y posibles excepciones de límites. Mi objetivo era minimizar el código y no anidar declaraciones if.
if (row == 0);
else (method (grid[row][col], grid[row-1][col]));
if (row == N-1);
else (method (grid[row][col], grid[row+1][col]));
if (col == 0);
else (method (grid[row][col], grid[row][col-1]));
if (col == N-1);<br>
else (method (grid[row][col], grid[row][col+1]));
donde el method(Doodad a, Doodad b)
realiza alguna operación entre a y b.
Alternativamente, puede usar el manejo de excepciones para evitar esta sintaxis, pero funciona y funciona bien para mi aplicación.
No puedo pensar en una ocasión en la que sea útil. Puede ser útil para bucles como
while(do something);
o
for(init; do something; something else);
Si utiliza el formato de su código en su IDE con regularidad, este tipo de errores se vuelven obvios. Algunos IDEs destacan esto como un error probable también.
Puedo pensar en un escenario donde se requiere una declaración vacía (no para condición if
, sino para while).
Cuando un programa solo quiere una confirmación explícita del usuario para continuar. Esto puede ser necesario cuando el trabajo después de la confirmación del usuario depende de otras cosas y el usuario desea tomar el control de cuándo proceder.
System.out.println("Enter Y to proceed. Waiting...");
System.out.println("");
while(!(new Scanner(System.in).next().equalsIgnoreCase("Y")));
System.out.println("Proceeding...");
// do the work here
Punto y coma al final de,
if (a == b); simplemente termine la declaración en una sola línea, lo que significa ignorar el resultado de la condición y continuar la ejecución desde la siguiente línea
Este código es útil, por otro lado, introduce algún error en el programa, por ejemplo,
caso 1.
a = 5;
b = 3;
if (a == b);
prinf ("a y b son iguales");
caso 2.
a = 5;
b = 5;
if (a == b);
prinf ("a y b son iguales");
imprimiría la misma salida en la pantalla ...
Si usa Eclipse, puede advertirle sobre esas declaraciones:
Si usa una instrucción if
, la primera instrucción después de if
se ejecutará si la condición es verdadera. Si tienes un bloque después del if
(con llaves), cuenta para ese bloque completo. Si no hay bloque, solo cuenta para una declaración. Un solo punto y coma es una declaración vacía. También podría escribir el código de su ejemplo de esta manera:
if(a==b) {
;
}
Solo un FYI sobre la usabilidad y qué diferencia hace o puede hacer si hay una declaración como esa
Considere un fragmento de código como el siguiente.
int a = 10;
if ((a = 50) == 50);
System.out.println("Value of a = " + a);
Claramente en este caso, la instrucción if
cambia la salida. Entonces una declaración como esa puede hacer la diferencia.
Esta es una situación donde esto podría ser útil o mejor para decir que tiene un impacto en el programa.
Un posible caso de uso:
if (a==b);
else {
// Do something
}
No es bueno, pero es posible.
Aún así, creo que la especificación Java debería rechazar un vacío if
.
if(a==b)
println("a equals b");
Puede usar una instrucción IF sin {}
si solo se debe ejecutar una sola línea, por lo que al usar if(a==b);
usted está diciendo si son iguales, ejecutan y vacían el enunciado ... Entonces no hará nada, y luego regresará a su ciclo normal, fuera del bloque IF.