Operador de acceso directo "or-assignment" ( / = ) en Java
Tengo un largo conjunto de comparaciones que hacer en Java, y me gustaría saber si una o más de ellas salen como verdaderas. La cadena de comparaciones era larga y difícil de leer, así que la rompí para facilitar la lectura, y automáticamente fui a usar 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 true si alguno de los valores predeterminados de
Del mismo modo, si quisiera realizar varias intersecciones lógicas, ¿podría usar &=
en lugar de &&
?
8 answers
El |=
es un compuesto operador de asignación (JLS 15.26.2) para el operador lógico booleano |
(JLS 15.22.2); no debe confundirse con el condicional-o ||
(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, para boolean b1, b2
, estos dos son equivalentes:
b1 |= b2;
b1 = b1 | b2;
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 evaluar ambos operandos -
&&
and||
evaluate the right operand conditionally; the right operand is evaluated only if its value could affect the result of the binary operation. Eso significa que el operando correcto NO se evalúa cuando:- El operando izquierdo de
&&
evalúa afalse
- (porque no importa a qué se evalúe el operando correcto, la expresión completa es
false
)
- (porque no importa a qué se evalúe el operando correcto, la expresión completa es
- El operando izquierdo de
||
evalúa atrue
- (porque no importa a qué se evalúe el operando correcto, la expresión completa es
true
)
- (porque no importa a qué se evalúe el operando correcto, la expresión completa es
- El operando izquierdo de
Así que volviendo a tu pregunta original, sí, esa construcción es válida, y mientras |=
no es exactamente un atajo equivalente para =
y ||
, calcula lo que quieres. 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 tenga cortocircuito es insignificante.
Hay casos, cuando se desea cortocircuitar, o incluso se requiere, pero su escenario no es uno de ellos.
Es lamentable que, a diferencia de otros lenguajes, Java no tenga &&=
y ||=
. Esto fue discutido en la pregunta ¿Por qué Java no tiene compuesto versiones de asignación de los operadores condicional-y y condicional-or? (&&=, ||=).
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:34:08
No es un operador de "atajo" (o cortocircuito) en la forma en que || y && son (en que no evaluarán el RHS si ya conocen el resultado basado en el LHS) pero hará lo que quieras en términos de trabajando.
Como ejemplo de la diferencia, este código estará bien si text
es null:
boolean nullOrEmpty = text == null || text.equals("")
Mientras que esto no:
boolean nullOrEmpty = false;
nullOrEmpty |= text == null;
nullOrEmpty |= text.equals(""); // Throws exception if text is null
(Obviamente se podría hacer "".equals(text)
para ese caso particular - solo estoy tratando de demostrar el principio.)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-03-21 09:12:10
Solo podrías tener una declaración. Expresado en múltiples líneas se lee casi exactamente como su código de ejemplo, solo que menos imperativo:
boolean negativeValue
= defaultStock < 0
| defaultWholesale < 0
| defaultRetail < 0
| defaultDelivery < 0;
Para 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 caro.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-09-17 18:31:54
Aunque podría ser excesivo para su problema, la biblioteca Guava tiene una sintaxis agradable con Predicate
s y hace una evaluación de cortocircuito de or/and Predicate
s.
Esencialmente, las comparaciones se convierten en objetos, se empaquetan en una colección y luego se iteran. Para o predicados, el primer golpe verdadero devuelve de la iteración, y viceversa para y.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-03-22 14:28:50
Si se trata de legibilidad, tengo el concepto de separación de datos probados de la lógica de prueba. Ejemplo de código:
// declare data
DataType [] dataToTest = new DataType[] {
defaultStock,
defaultWholesale,
defaultRetail,
defaultDelivery
}
// define logic
boolean checkIfAnyNegative(DataType [] data) {
boolean negativeValue = false;
int i = 0;
while (!negativeValue && i < data.length) {
negativeValue = data[i++] < 0;
}
return negativeValue;
}
El código se ve más detallado y se explica por sí mismo. Incluso puede crear una matriz en la llamada al método, como esta:
checkIfAnyNegative(new DataType[] {
defaultStock,
defaultWholesale,
defaultRetail,
defaultDelivery
});
Es más legible que 'comparison string', y también tiene la ventaja de rendimiento de cortocircuitar (a costa de la asignación de matrices y la llamada a métodos).
Editar: Incluso más legibilidad se puede lograr simplemente mediante el uso parámetros de varargs:
La firma del método sería:
boolean checkIfAnyNegative(DataType ... data)
Y la llamada podría verse así:
checkIfAnyNegative( defaultStock, defaultWholesale, defaultRetail, defaultDelivery );
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-04-26 08:11:53
List<Integer> params = Arrays.asList (defaultStock, defaultWholesale,
defaultRetail, defaultDelivery);
int minParam = Collections.min (params);
negativeValue = minParam < 0;
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-03-21 09:21:31
/ / booleano lógico O
/ bitwise OR
/ = operador OR y asignación inclusivo a bit
La razón por la que |= no hace shortcircit es porque hace un OR lógico O no. Es decir:
C |= 2 is same as C = C | 2
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-01-11 19:15:04
Es un post antiguo, pero con el fin de proporcionar una perspectiva diferente para 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:
int a = 10; // a = 10
a += 5; // a = 15
¿Cuál era el punto de esto? Era para evitar escribir la variable a
dos veces en la misma línea. (¿Me estoy perdiendo algo superior aquí?)
Entonces, la siguiente línea hace exactamente lo mismo, evitando escribir la variable b1
dos veces en la misma línea.
b1 |= b2;
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-04-17 08:53:57