Primero, algunos antecedentes: soy un maestro de TI en formación y estoy tratando de presentar a los operadores booleanos de Java a mi clase de décimo grado. Mi maestro-mentor examinó una hoja de trabajo que preparé y comentó que podría dejarles usar solo una & o | para denotar a los operadores, porque "hacen lo mismo".
Soy consciente de la diferencia entre & y &&.
& es un operador bit a bit destinado a ser utilizado entre enteros, para realizar "bit-twiddling".
&& es un operador condicional destinado a usarse entre valores booleanos.
Para probar el punto de que estos operadores no siempre "hacen lo mismo", me propuse encontrar un ejemplo en el que el uso de los valores booleanos entre bits produjera un error. Encontré este ejemplo
boolean bitwise;
boolean conditional;
int i=10, j=12;
bitwise = (i<j) | ((i=3) > 5); // value of i after oper: 3
System.out.println(bitwise+ " "+ i);
i=10;
conditional = (i<j) || (i=3) > 5 ; // value of i after oper: 10
System.out.println(conditional+ " "+ i);
i=10;
bitwise = (i>j) & (i=3) > 5; // value of i after oper: 3
System.out.println(bitwise+ " "+ i);
i=10;
conditional = (i>j) && (i=3) > 5; // value of i after oper: 10
System.out.println(conditional+ " "+ i);
Este ejemplo muestra que si un valor tiene que cambiarse en la segunda mitad de la expresión, esto conduciría a una diferencia entre los resultados, ya que bitwise es un operador ansioso, mientras que el condicional se comporta como un cortocircuito (no evalúa el segundo mitad, si la primera mitad es falsa en el caso de && y verdadera en el caso de ||).
Tengo un problema con este ejemplo. ¿Por qué querrías cambiar un valor al mismo tiempo que lo comparas? No parece una forma robusta de codificar. Siempre he sido reacio a realizar múltiples operaciones en una sola línea en mi código de producción. Parece algo que haría un "vaquero codificador" sin conciencia en cuanto a la facilidad de mantenimiento de su código. Sé que en algunos dominios el código debe ser lo más compacto posible, pero ¿seguramente esta es una mala práctica en general?
Puedo explicar mi elección de fomentar el uso de && y || sobre y y | porque esta es una convención de codificación aceptada en ingeniería de software .
Pero, ¿podría alguien darme un ejemplo mejor, incluso del mundo real, del uso de un operador bit a bit en una expresión condicional?
fuente
bitwise = !(true & true == false);
ycondition = !(true && true == false);
ambos se evaluarán como verdaderos, ¿entonces en este caso son intercambiables? Tal vez sintácticamente, ya que el código aún se compila. Estoy de acuerdo en que se usan semánticamente para diferentes cosas, como mencioné en el párrafo 2. ¡Dices eso! y & "casi nunca aparecen en un condicional por sí mismos". Estoy buscando estos casos de "casi nunca" y me pregunto si existen legítimamente.Los operadores no bit a bit
&&
y||
son operadores de cortocircuito. En otras palabras, con&&
, si el LHS es falso, el RHS nunca será evaluado; con||
si el LHS es verdadero, entonces el RHS nunca será evaluado. Por otro lado, los operadores bit a bit&
y|
no son de cortocircuito, y siempre evaluarán tanto el LHS como el RHS. De lo contrario, son equivalentes en unaif
declaración.El único momento en que puedo ver el valor al usar los operadores que no son de cortocircuito es si el RHS tiene algún tipo de efecto secundario deseable que desea que ocurra en todos los casos. No puedo pensar en un ejemplo específico en el que quieras esto, y no creo que sea una buena práctica, pero esa es la diferencia.
fuente
La respuesta filosófica general es que el uso de operadores bit a bit para operadores booleanos es atípico y hace que el código sea más difícil de leer. En la práctica (para el código que está en producción), un código más legible es más fácil de mantener y, por lo tanto, más deseable.
Para un uso real de la necesidad de operadores de cortocircuito, vea casos como:
Este tipo de operaciones se muestran con frecuencia en el código del mundo real.
fuente
&
es "más difícil de leer" que 2? No tengo un ejemplo en el que los 2 operadores no funcionen de la misma manera para los operandos booleanos. Estoy de acuerdo con su punto sobre un código más legible y más fácil de mantener. Quiero alentarlos a escribir un código hermoso. Pero tener alguna prueba en mi bolsa de herramientas sería más convincente que "porque lo dije". Lo tengo establecido como estándar en ese enlace, y es posible que tenga que confiar solo en eso si no obtengo el ejemplo que estoy buscando. Como le pregunté a @Steve Haigh: ¿Java debería indicar esto como un uso incorrecto?Utilizará operadores bit a bit si compara las enumeraciones de Bitmask. Por ejemplo, tiene una enumeración de estados y un objeto que puede estar en más de uno de esos estados. En este caso, hará un bit a bit o para asignar más de un estado a su objeto.
por ejemplo
state = CONNECTED | IN_PROGRESS
dondeCONNECTED could be 0x00000001
yIN_PROGRESS 0x00000010
Para obtener más información, busque la documentación de las enumeraciones de la bandera.
fuente
Un ejemplo más simple de error:
aquí tienes dos condiciones, ambas son distintas de cero; pero el bit a bit
&
resulta en cero.fuente
(condA && condB)
errores, porque && no funciona durante 2int
s, solo 2 booleanos.(condA & condB)
si bien es correcto, se evalúa como anint
y en java no podemos decirlo,if(int)
por lo que también es un error. Sin embargo, eres el primero en entender lo que estoy buscando, exactamente ese ejemplo de error .(Boolean(condA) && Boolean(condB))
(creo queBoolean(x)
estrue
para enteros distintos de cero, ¿verdad?)((condA!=0) && (condB!=0))
?if (((condA!=0) && (condB!=0))) { System.out.println("correct"); } if (((condA!=0) & (condB!=0))) { System.out.println("never executed?"); }
ejecuta ambas declaraciones de impresión.