Tengo un largo conjunto de comparaciones que hacer en Java y me gustaría saber si una o más de ellas resultan verdaderas. La cadena de comparaciones era larga y difícil de leer, así que la dividí para facilitar la lectura y automáticamente usé un operador de acceso directo en |=
lugar de negativeValue = negativeValue || boolean
.
boolean negativeValue = false;
negativeValue |= (defaultStock < 0);
negativeValue |= (defaultWholesale < 0);
negativeValue |= (defaultRetail < 0);
negativeValue |= (defaultDelivery < 0);
Espero que negativeValue
sea cierto si alguno de los valores predeterminados de <algo> es negativo. ¿Es esto válido? ¿Hará lo que espero? No pude verlo mencionado en el sitio de Sun o stackoverflow, pero Eclipse no parece tener ningún problema y el código se compila y se ejecuta.
De manera similar, si quisiera realizar varias intersecciones lógicas, ¿podría usar en &=
lugar de &&
?
java
assignment-operator
compound-assignment
or-operator
David Mason
fuente
fuente
||=
operador inexistente , pero|=
es la forma de combinación del operador u bit a bit.|=
un cortocircuito sería inconsistente con otros operadores de asignación compuesta, yaa |= b;
que no sería lo mismo quea = a | b;
, con la advertencia habitual de evaluara
dos veces (si es que importa). Me parece que la gran decisión de comportamiento lingüístico fue no tomar||=
, así que me pierdo el punto.Respuestas:
El
|=
es un operador de asignación compuesto ( JLS 15.26.2 ) para el operador lógico booleano|
( JLS 15.22.2 ); no debe confundirse con el condicional-or||
( JLS 15.24 ). También hay&=
y^=
correspondientes a la versión de asignación compuesta de la lógica booleana&
y^
respectivamente.En otras palabras,
boolean b1, b2
estos dos son equivalentes:La diferencia entre los operadores lógicos (
&
y|
) en comparación con sus contrapartes condicionales (&&
y||
) es que los primeros no "cortocircuitan"; los últimos lo hacen. Es decir:&
y|
siempre evalúe ambos operandos&&
y||
evaluar el operando correcto condicionalmente ; el operando derecho se evalúa solo si su valor podría afectar el resultado de la operación binaria. Eso significa que el operando correcto NO se evalúa cuando:&&
evalúa comofalse
false
)||
evalúa comotrue
true
)Entonces, volviendo a su pregunta original, sí, esa construcción es válida, y aunque
|=
no es exactamente un atajo equivalente para=
y||
, calcula lo que desea. Dado que el lado derecho del|=
operador en su uso es una simple operación de comparación de enteros, el hecho de que|
no se cortocircuite es insignificante.Hay casos en los que se desea, o incluso se requiere, un cortocircuito, pero su escenario no es uno de ellos.
Es lamentable que, a diferencia de otros lenguajes, Java no tenga
&&=
y||=
. Esto se discutió en la pregunta ¿Por qué Java no tiene versiones de asignación compuesta de los operadores condicional-and y condicional-or? (&& =, || =) .fuente
|
No es un operador de "atajo" (o cortocircuito) de la manera que || y && son (en el sentido de que no evaluarán el RHS si ya conocen el resultado basado en el LHS) pero hará lo que quieras en términos de trabajo .
Como ejemplo de la diferencia, este código estará bien si
text
es nulo:mientras que esto no:
(Obviamente, podría hacerlo
"".equals(text)
para ese caso en particular, solo estoy tratando de demostrar el principio).fuente
Podrías tener solo una declaración. Expresado en varias líneas, se lee casi exactamente como su código de muestra, solo que menos imperativo:
Para las expresiones más simples, usar
|
puede ser más rápido que||
porque, aunque evita hacer una comparación, significa usar una rama implícitamente y eso puede ser muchas veces más costoso.fuente
Aunque puede ser excesivo para su problema, la biblioteca de Guava tiene una buena sintaxis con
Predicate
sy realiza una evaluación de cortocircuito de o yPredicate
s.Esencialmente, las comparaciones se convierten en objetos, se empaquetan en una colección y luego se repiten. Para predicados o, el primer acierto verdadero regresa de la iteración, y viceversa para y.
fuente
Si se trata de legibilidad, tengo el concepto de separación de datos probados de la lógica de prueba. Muestra de código:
El código parece más detallado y autoexplicativo. Incluso puede crear una matriz en la llamada al método, como esta:
Es más legible que la 'cadena de comparación' y también tiene la ventaja de rendimiento del cortocircuito (a costa de la asignación de la matriz y la llamada al método).
Editar: Se puede lograr incluso más legibilidad simplemente usando parámetros varargs:
La firma del método sería:
Y la llamada podría verse así:
fuente
Es una publicación antigua, pero para brindar una perspectiva diferente a los principiantes, me gustaría dar un ejemplo.
Creo que el caso de uso más común para un operador compuesto similar sería
+=
. Estoy seguro de que todos escribimos algo como esto:¿Cuál fue el punto de esto? El objetivo era evitar la repetición y eliminar el código repetitivo.
Entonces, la siguiente línea hace exactamente lo mismo, evitando escribir la variable
b1
dos veces en la misma línea.fuente
longNameOfAccumulatorAVariable += 5;
vs.longNameOfAccumulatorAVariable = longNameOfAccumulatorVVariable + 5;
fuente
negativeValue = defaultStock < 0 || defaultWholesale < 0
etc. Aparte de la ineficacia de todo el encajonamiento y envoltura que está sucediendo aquí, no me resulta tan fácil entender lo que realmente significaría su código.|| OR lógico booleano
| O bit a bit
| = operador de asignación y OR inclusivo bit a bit
La razón por la que | = no tiene un cortocircuito es porque hace un OR bit a bit O no un OR lógico. Es decir:
Tutorial para operadores java
fuente
|
es OR entero bit a bit, pero también es OR lógico; consulte la Especificación del lenguaje Java 15.22.2.