Así que para los operadores binarios en booleanos, Java tiene &
, |
, ^
, &&
y ||
.
Resumamos brevemente lo que hacen aquí:
- JLS 15.22.2 Operadores lógicos booleanos &, ^ y |
- JLS 15.23 Condicional-Y operador &&
- JLS 15.24 Operador O condicional ||
Porque
&
, el valor del resultado estrue
si ambos valores de operando sontrue
; de lo contrario, el resultado esfalse
.Porque
|
, el valor del resultado esfalse
si ambos valores de operando sonfalse
; de lo contrario, el resultado estrue
.Porque
^
, el valor del resultado estrue
si los valores del operando son diferentes; de lo contrario, el resultado esfalse
.El
&&
operador es similar,&
pero evalúa su operando de la derecha solo si el valor de su operando de la izquierda estrue
.El
||
operador es como|
, pero evalúa su operando de la derecha solo si el valor de su operando de la izquierda esfalse
.
Ahora, entre los 5, 3 de ellos tienen versiones de asignación compuesta, a saber |=
, &=
y ^=
. Entonces mi pregunta es obvia: ¿por qué Java no proporciona &&=
y ||=
también? Encuentro que los necesito más de lo que necesito &=
y |=
.
Y no creo que "porque es demasiado largo" sea una buena respuesta, porque Java lo ha hecho >>>=
. Debe haber una mejor razón para esta omisión.
De 15.26 Operadores de asignación :
Hay 12 operadores de asignación; [...]
= *= /= %= += -= <<= >>= >>>= &= ^= |=
Se hizo un comentario de que si &&=
y ||=
se llevaron a cabo, entonces sería los únicos operadores que no evalúan el lado derecho primero. Creo que esta noción de que un operador de asignación compuesta evalúa primero el lado derecho es un error.
Desde 15.26.2 Operadores de asignación compuesta :
Una expresión de asignación compuesta de la forma
E1 op= E2
es equivalente aE1 = (T)((E1) op (E2))
, dondeT
es el tipo deE1
, excepto queE1
se evalúa solo una vez.
Como prueba, el siguiente fragmento arroja un NullPointerException
, no un ArrayIndexOutOfBoundsException
.
int[] a = null;
int[] b = {};
a[0] += b[-1];
fuente
Respuestas:
Razón
Los operadores
&&=
y||=
no están disponibles en Java porque para la mayoría de los desarrolladores estos operadores son:Ejemplo para
&&=
Si Java permitió el
&&=
operador, entonces ese código:bool isOk = true; //becomes false when at least a function returns false isOK &&= f1(); isOK &&= f2(); //we may expect f2() is called whatever the f1() returned value
sería equivalente a:
bool isOk = true; if (isOK) isOk = f1(); if (isOK) isOk = f2(); //f2() is called only when f1() returns true
Este primer código es propenso a errores porque muchos desarrolladores pensarían que
f2()
siempre se llama cualquiera que sea el valor devuelto por f1 (). Es comobool isOk = f1() && f2();
dondef2()
se llama solo cuandof1()
vuelvetrue
.Si el desarrollador quiere
f2()
ser llamado solo cuandof1()
regresatrue
, por lo tanto, el segundo código anterior es menos propenso a errores.De lo contrario,
&=
es suficiente porque el desarrollador quieref2()
que siempre se le llame:Mismo ejemplo pero para
&=
bool isOk = true; isOK &= f1(); isOK &= f2(); //f2() always called whatever the f1() returned value
Además, la JVM debería ejecutar este código anterior como el siguiente:
bool isOk = true; if (!f1()) isOk = false; if (!f2()) isOk = false; //f2() always called
Comparar
&&
y&
resultadosSon los resultados de los operadores
&&
y&
la misma cuando se aplica sobre valores booleanos?Comprobemos usando el siguiente código Java:
public class qalcdo { public static void main (String[] args) { test (true, true); test (true, false); test (false, false); test (false, true); } private static void test (boolean a, boolean b) { System.out.println (counter++ + ") a=" + a + " and b=" + b); System.out.println ("a && b = " + (a && b)); System.out.println ("a & b = " + (a & b)); System.out.println ("======================"); } private static int counter = 1; }
Salida:
1) a=true and b=true a && b = true a & b = true ====================== 2) a=true and b=false a && b = false a & b = false ====================== 3) a=false and b=false a && b = false a & b = false ====================== 4) a=false and b=true a && b = false a & b = false ======================
Por lo tanto SÍ podemos reemplazar
&&
por&
valores booleanos ;-)Así que es mejor usarlo en
&=
lugar de&&=
.Igual por
||=
Las mismas razones que para
&&=
: eloperador
|=
es menos propenso a errores que||=
.Si un desarrollador desea que
f2()
no lo llamen cuandof1()
regresetrue
, le aconsejo las siguientes alternativas:// here a comment is required to explain that // f2() is not called when f1() returns false, and so on... bool isOk = f1() || f2() || f3() || f4();
o:
// here the following comments are not required // (the code is enough understandable) bool isOk = false; if (!isOK) isOk = f1(); if (!isOK) isOk = f2(); //f2() is not called when f1() returns false if (!isOK) isOk = f3(); //f3() is not called when f1() or f2() return false if (!isOK) isOk = f4(); //f4() is not called when ...
fuente
&
y&&
da los mismos resultados. Muchas gracias por su colaboración. Te gusta mi respuesta Salud.if (a) a = b
para la velocidada&=b;
es más rápido queif(a) a=b;
cuando se usan valores almacenados en los registros de la CPU. Sin embargo, sib
está en la memoria externa (no en caché),if(a) a=b;
es más rápido. ¿Es a lo que te refieres? Proporcione más código de ejemplo ;-) Tengo curiosidad por conocer su opinión. Nos vemos. SaludosisOK &&= f2();
me gustaría que hiciera un cortocircuito como lo&&
hace.A = A op B
, de modo que todos sepan perfectamente lo que están haciendo y puedan ocuparse de las implicaciones. Si sus razones fueran realmente la causa de su ausencia, lo vería como una condescendencia no deseada. Sin embargo, quiero agradecerles por agregar la líneabool isOk = f1() || f2() || f3() || f4();
porque eso es lo que estaba ciego para verme.Probablemente porque algo como
x = false; x &&= someComplexExpression();
parece que debería asignar
x
y evaluarsomeComplexExpression()
, pero el hecho de que la evaluación depende del valor dex
no es evidente en la sintaxis.También porque la sintaxis de Java se basa en C, y nadie vio la necesidad urgente de agregar esos operadores. De todos modos, probablemente estaría mejor con una declaración if.
fuente
x() && y()
parece que debería evaluar ambos lados de la expresión. Obviamente, la gente acepta que&&
es un cortocircuito, por lo que también debería seguir&&=
.a -= b;
funcionaría de manera completamente diferente aa &&= b;
.Es así en Java, porque es así en C.
Ahora, la pregunta de por qué es así en C es porque cuando & y && se convirtieron en operadores diferentes (en algún momento antes del descenso de C de B), la variedad & = de operadores simplemente se pasó por alto.
Pero la segunda parte de mi respuesta no tiene ninguna fuente que la respalde.
fuente
En gran parte porque la sintaxis de Java se basa en C (o al menos la familia C), y en C todos esos operadores de asignación se compilan en instrucciones de ensamblaje aritméticas o bit a bit en un solo registro. La versión del operador de asignación evita los temporales y puede haber producido un código más eficiente en los primeros compiladores no optimizados. Los operadores lógicos (como se denominan en C) equivalentes (
&&=
y||=
) no tienen una correspondencia tan obvia con instrucciones de ensamblaje individuales; generalmente se expanden a una secuencia de instrucciones de prueba y ramificación.Curiosamente, idiomas como el rubí no tienen || = y = &&.
Editar: la terminología difiere entre Java y C
fuente
&
,|
y^
;&&
y||
son los operadores condicionales.bool
tipo. Son 20 años en la historia del lenguaje sin bool. No había ninguna razón para hacerlo&&=
. las operaciones bit a bit fueron suficientes.Uno de los objetivos originales de Java era ser "simple, orientado a objetos y familiar". Según se aplica a este caso, & = es familiar (C, C ++ lo tiene y familiar en este contexto significa familiar para alguien que conoce a esos dos).
&& = no sería familiar, y no sería simple, en el sentido de que los diseñadores del lenguaje no buscaban pensar en todos los operadores que podrían agregar al lenguaje, por lo que menos operadores adicionales son más simples.
fuente
Para variables booleanas, && y || usaría la evaluación de cortocircuito mientras & y | no lo haga, por lo que esperaría que && = y || = también usen la evaluación de cortocircuito. Hay un buen caso de uso para esto. Especialmente si está iterando sobre un bucle, desea ser rápido, eficiente y conciso.
En lugar de escribir
foreach(item in coll) { bVal = bVal || fn(item); // not so elegant }
Quiero escribir
foreach(item in coll) { bVal ||= fn(item); // elegant }
y sepa que una vez que bVal sea verdadero, no se llamará a fn () durante el resto de las iteraciones.
fuente
if (fn(item)) { bVal = true; break; }
.'
&
' y '&&
' no son lo mismo que '&&
' es una operación de atajo que no funcionará si el primer operando es falso mientras '&
' lo hará de todos modos (funciona tanto con números como con booleanos).Estoy de acuerdo en que tiene más sentido existir, pero no es tan malo si no está ahí. Supongo que no estaba ahí porque C no lo tiene.
Realmente no puedo pensar en por qué.
fuente
Está permitido en Ruby.
Si tuviera que adivinar, diría que no se usa con frecuencia, por lo que no se implementó. Otra explicación podría ser que el analizador solo mira el carácter antes de =
fuente
No puedo pensar en una razón mejor que '¡Se ve increíblemente feo!'
fuente
&&=
feoY
verifica ambos operandos, es un operador bit a bit. Java define varios operadores bit a bit, que se pueden aplicar a los tipos enteros, long, int, short, char y byte.
&&
deja de evaluar si el primer operando se evalúa como falso ya que el resultado será falso, es un operador lógico. Se puede aplicar a valores booleanos.
El operador && es similar al operador &, pero puede hacer que su código sea un poco más eficiente. Debido a que ambas expresiones comparadas por el operador & deben ser verdaderas para que toda la expresión sea verdadera, no hay razón para evaluar la segunda expresión si la primera devuelve falso. El operador & siempre evalúa ambas expresiones. El operador && evalúa la segunda expresión solo si la primera expresión es verdadera.
Tener un operador de asignación && = no agregaría realmente una nueva funcionalidad al idioma. La aritmética del operador bit a bit es mucho más expresiva, puede hacer aritmética bit a bit enteros, que incluye aritmética booleana. Los operadores lógicos pueden simplemente hacer aritmética booleana.
fuente
Brian Goetz (arquitecto de lenguaje Java en Oracle) escribió :
fuente
a & b y a && b no son lo mismo.
a && b es una expresión booleana que devuelve un booleano, y a & b es una expresión bit a bit que devuelve un int (si a y b son ints).
¿Qué crees que son iguales?
fuente