java - operator - ¿Por qué solemos usar `||` no `|`, ¿cuál es la diferencia?
operador>> java (26)
Solo me pregunto por qué solemos usar OR lógico ||
entre dos booleanos no bit a bit O |
, aunque ambos funcionan bien.
Quiero decir, mira lo siguiente:
if(true | true) // pass
if(true | false) // pass
if(false | true) // pass
if(false | false) // no pass
if(true || true) // pass
if(true || false) // pass
if(false || true) // pass
if(false || false) // no pass
Podemos usar |
en lugar de ||
? Lo mismo con &
y &&
.
Además del cortocircuito, otra cosa a tener en cuenta es que realizar una operación lógica bit a bit en valores que pueden ser distintos de 0 o 1 tiene un significado muy diferente al de la lógica condicional. Mientras que USUALMENTE es el mismo para |
y ||
, con &
y &&
obtiene resultados muy diferentes (por ejemplo, 2 & 4
es 0 / falso, mientras que 2 && 4
es 1 / verdadero).
Si lo que obtienes de una función es en realidad un código de error y estás probando el no-cero, esto puede importar bastante.
Esto no es un problema tan grande en Java donde tienes que encasillar explícitamente a boolean o comparar con 0 o similar, pero en otros lenguajes con sintaxis similar (C / C ++ et al) puede ser bastante confuso.
Además, tenga en cuenta que & y | solo se puede aplicar a valores de tipo entero, y no a todo lo que puede ser equivalente a una prueba booleana. Nuevamente, en lenguajes que no son Java, hay bastantes cosas que se pueden usar como booleano con una comparación implícita != 0
(punteros, flotantes, objetos con un operator bool()
, etc.) y los operadores bit a bit son casi siempre sin sentido en esos contextos.
Lógica ||
y & consulte el lado derecho solo si es necesario. El |
y compruebe ambos todo el tiempo.
Por ejemplo:
int i = 12;
if (i == 10 & i < 9) // It will check if i == 10 and if i < 9
...
Reescribirlo:
int i = 12;
if (i == 10 && i < 9) // It will check if i == 10 and stop checking afterward because i doesn''t = 10
...
Otro ejemplo:
int i = 12;
if (i == 12 | i > 10) // It will check if i == 12 and it will check if i > 10
...
Reescribirlo:
int i = 12;
if (i == 12 || i > 10) // It will check if i == 12, it does, so it stops checking and executes what is in the if statement
...
Los operadores ||
y &&
se llaman operadores condicionales , mientras |
y se llaman operadores bit a bit . Ellos sirven diferentes propósitos.
Los operadores condicionales solo funcionan con expresiones que evalúan estáticamente a boolean
en los lados izquierdo y derecho.
Los operadores bit a bit trabajan con cualquier operando numérico.
Si desea realizar una comparación lógica, debe usar operadores condicionales , ya que agregará algún tipo de seguridad de tipo a su código.
Si usas el ||
y &&
formas, en lugar de |
y &
formas de estos operadores, Java no se molestará en evaluar solo el operando de la mano derecha.
Se trata de si desea provocar un cortocircuito en la evaluación o no, la mayoría del tiempo que desee.
Una buena forma de ilustrar los beneficios del cortocircuito sería considerar el siguiente ejemplo.
Boolean b = true;
if(b || foo.timeConsumingCall())
{
//we entered without calling timeConsumingCall()
}
Otro beneficio, como mencionaron Jeremy y Peter, para los cortocircuitos es el cheque de referencia nulo:
if(string != null && string.isEmpty())
{
//we check for string being null before calling isEmpty()
}
Además del hecho de que | es un operador bit a bit: || es un operador de cortocircuito: cuando un elemento es falso, no verifica los demás.
if(something || someotherthing)
if(something | someotherthing)
si algo es VERDADERO, || no evaluará a alguien más, mientras | va a hacer Si las variables en tus sentencias if son en realidad llamadas a funciones, usando || posiblemente esté ahorrando mucho rendimiento.
Echa un vistazo a:
http://java.sun.com/docs/books/tutorial/java/nutsandbolts/operators.html
| es a nivel de bit inclusive O
|| es lógico O
| = en bit o, || = lógica o
| es un operador bit a bit || es un operador lógico
Uno tomará dos bits y / o ellos.
Uno determinará la verdad (esto O eso) Si esto es cierto o si es verdadero, entonces la respuesta es verdadera.
Ah, y las personas responden estas preguntas rápidamente.
|| devuelve un valor booleano al poner en OR dos valores (es por eso que se lo conoce como LOGICAL o)
ES DECIR:
if (A || B)
Devolvería verdadero si A o B es verdadero, o falso si ambos son falsos.
| es un operador que realiza una operación bit a bit en dos valores. Para entender mejor las operaciones bit a bit, puedes leer aquí:
|| es el operador lógico u operador mientras | es el operador bit a bit
boolean a = true;
boolean b = false;
if (a || b) {
}
int a = 0x0001;
a = a | 0x0002;
|| es un o lógico | es un poco sabio o.
| es bit a bit o, || es lógico o.
| is the binary or operator
|| is the logic or operator
Una nota al margen: Java tiene | = pero no es un || =
Un ejemplo de cuándo debes usar || es cuando la primera expresión es una prueba para ver si la segunda expresión explotaría. por ejemplo, utilizando un solo | en el siguiente caso podría resultar en un NPE.
public static boolean isNotSet(String text) {
return text == null || text.length() == 0;
}
La única vez que usarías |
o &
lugar de ||
o &&
es cuando tienes expresiones booleanas muy simples y el costo del corte corto (es decir, una rama) es mayor que el tiempo que guardas al no evaluar las expresiones posteriores.
Sin embargo, esta es una micro-optimización que rara vez importa, excepto en el código de nivel más bajo.
También note una trampa común: los operadores no perezosos tienen preferencia sobre los perezosos, entonces:
boolean a, b, c;
a || b && c; //resolves to a || (b && c)
a | b && c; //resolves to (a | b) && c
Tenga cuidado al mezclarlos.
Una diferencia principal es que || y && exhibir "cortocircuito", por lo que el RHS solo se evaluará si es necesario.
Por ej.
if (a || b) {
path1...
} else {
path2..
}
Arriba si a es verdadero, entonces b no se probará y se ejecutará la ruta 1. Si | fue utilizado, ambos lados serían evaluados incluso si ''a'' es verdadero.
Vea Aquí y aquí , para obtener un poco más de información.
Espero que esto ayude.
|
no realiza la evaluación de cortocircuito en expresiones booleanas. ||
dejará de evaluar si el primer operando es verdadero, pero |
no lo hará
Además, |
se puede usar para realizar la operación O bit a bit en los valores byte / short / int / long. ||
no poder.
a | b: evaluar b en cualquier caso
a || b: evalúa b solo si se evalúa como falso
usualmente uso cuando hay un incremento previo y un operador de incremento de post. Mira el siguiente código:
package ocjpPractice;
/**
* @author tithik
*
*/
public class Ex1 {
public static void main(String[] args) {
int i=10;
int j=9;
int x=10;
int y=9;
if(i==10 | ++i>j){
System.out.println("it will print in first if");
System.out.println("i is: "+i);
}
if(x==10 ||++x>y){
System.out.println("it will print in second if");
System.out.println("x is: "+x);
}
}
}
salida:
se imprimirá primero si
yo soy: 11
se imprimirá en el segundo si
x es: 10
ambos if
bloques son iguales pero el resultado es diferente. cuando hay |
, ambas condiciones serán evaluadas. Pero si es ||
, no evaluará la segunda condición ya que la primera condición ya es verdadera.
Entonces, para construir sobre las otras respuestas con un ejemplo, el cortocircuito es crucial en los siguientes controles defensivos:
if (foo == null || foo.isClosed()) {
return;
}
if (bar != null && bar.isBlue()) {
foo.doSomething();
}
Usando |
y, en su lugar, podría dar lugar a que se NullPointerException
una NullPointerException
aquí.
No cortocircuito puede ser útil. A veces quieres asegurarte de que dos expresiones evalúen. Por ejemplo, supongamos que tiene un método que elimina un objeto de dos listas separadas. Es posible que desee hacer algo como esto:
class foo {
ArrayList<Bar> list1 = new ArrayList<Bar>();
ArrayList<Bar> list2 = new ArrayList<Bar>();
//Returns true if bar is removed from both lists, otherwise false.
boolean removeBar(Bar bar) {
return (list1.remove(bar) & list2.remove(bar));
}
}
Si su método en su lugar usó el operando condicional, no podría eliminar el objeto de la segunda lista si la primera lista devolvió falso.
//Fails to execute the second remove if the first returns false.
boolean removeBar(Bar bar) {
return (list1.remove(bar) && list2.remove(bar));
}
No es increíblemente útil, y (como con la mayoría de las tareas de programación) puede lograrlo con otros medios. Pero es un caso de uso para operandos bit a bit.
Hay muchos casos de uso que sugieren por qué debería elegir ||
en lugar de |
. Algunos casos de uso tienen que usar |
operador para verificar todas las condiciones.
Por ejemplo, si desea verificar la validación del formulario y desea mostrar al usuario todos los campos no válidos con textos de error en lugar de solo un primer campo no válido.
||
operador sería,
if(checkIfEmpty(nameField) || checkIfEmpty(phoneField) || checkIfEmpty(emailField)) {
// invalid form with one or more empty fields
}
private boolean checkIfEmpty(Widget field) {
if(field.isEmpty()) {
field.setErrorMessage("Should not be empty!");
return true;
}
return false;
}
Por lo tanto, con el fragmento de arriba, si el usuario envía el formulario con TODOS los campos vacíos, SÓLO se mostrará el campo de nombre con mensaje de error. Pero, si lo cambias a,
if(checkIfEmpty(nameField) | checkIfEmpty(phoneField) | checkIfEmpty(emailField)) {
// invalid form with one or more empty fields
}
Mostrará un mensaje de error apropiado en cada campo, independientemente de true
condiciones true
.
Las otras respuestas han hecho un buen trabajo al cubrir la diferencia funcional entre los operadores, pero las respuestas podrían aplicarse a casi todos los lenguajes derivados de C que existen en la actualidad. La pregunta está etiquetada con java , por lo que intentaré responder específica y técnicamente para el lenguaje Java.
&
y |
puede ser Operadores de bits enteros u Operadores lógicos booleanos. La sintaxis para los operadores lógicos y bit a bit ( §15.22 ) es:
AndExpression:
EqualityExpression
AndExpression & EqualityExpression
ExclusiveOrExpression:
AndExpression
ExclusiveOrExpression ^ AndExpression
InclusiveOrExpression:
ExclusiveOrExpression
InclusiveOrExpression | ExclusiveOrExpression
La sintaxis para EqualityExpression
se define en §15.21 , que requiere RelationalExpression
definida en §15.20 , que a su vez requiere ShiftExpression
y ReferenceType
definidos en §15.19 y §4.3 , respectivamente. ShiftExpression
requiere AdditiveExpression
definido en §15.18 , que continúa profundizando, definiendo la aritmética básica, operadores unarios, etc. ReferenceType
profundiza en todas las formas de representar un tipo. (Aunque ReferenceType
no incluye los tipos primitivos, la definición de tipos primitivos es en última instancia necesaria, ya que pueden ser del tipo de dimensión para una matriz, que es un ReferenceType
).
Los operadores bitwise y lógicos tienen las siguientes propiedades:
- Estos operadores tienen diferente precedencia, con
&
tienen la mayor precedencia y|
la precedencia más baja.- Cada uno de estos operadores es sintácticamente asociativo a la izquierda (cada grupo de izquierda a derecha).
- Cada operador es conmutativo si las expresiones del operando no tienen efectos secundarios.
- Cada operador es asociativo.
- Los operadores lógicos y de bit se pueden usar para comparar dos operandos de tipo numérico o dos operandos de tipo
boolean
. Todos los demás casos dan como resultado un error en tiempo de compilación.
La distinción entre si el operador sirve como operador bit a bit o como operador lógico depende de si los operandos son "convertibles a un tipo integral primitivo" ( §4.2 ) o si son de tipo boolean
o Boolean
( §5.1.8 ).
Si los operandos son tipos integrales, la promoción numérica binaria ( §5.6.2 ) se realiza en ambos operandos, dejándolos a ambos como long
s o int
s para la operación. El tipo de operación será el tipo de operandos (promocionados). En ese punto, &
será bit a bit AND, ^
será a nivel de bit exclusivo O, y |
será bit a bit inclusive ( §15.22.1 )
Si los operandos son boolean
o Boolean
, los operandos estarán sujetos a la conversión de unboxing si es necesario ( §5.1.8 ), y el tipo de operación será boolean
. &
dará como resultado true
si ambos operandos son true
, ^
dará como resultado true
si ambos operandos son diferentes, y |
dará como resultado true
si cualquiera de los operandos es true
. ( §15.22.2 )
Por el contrario, &&
es el "operador condicional" ( §15.23 ) y ||
es el "operador condicional" ( §15.24 ). Su sintaxis se define como:
ConditionalAndExpression:
InclusiveOrExpression
ConditionalAndExpression && InclusiveOrExpression
ConditionalOrExpression:
ConditionalAndExpression
ConditionalOrExpression || ConditionalAndExpression
&&
es como &
, excepto que solo evalúa el operando correcto si el operando de la izquierda es true
. ||
es como |
, excepto que solo evalúa el operando correcto si el operando de la izquierda es false
.
Conditional-Y tiene las siguientes propiedades:
- El operador condicional y es sintácticamente asociativo de izquierda (se agrupa de izquierda a derecha).
- El operador condicional y es totalmente asociativo con respecto a los efectos secundarios y el valor del resultado. Es decir, para cualquier expresión
a
,b
, yc
, la evaluación de la expresión((a) && (b)) && (c)
produce el mismo resultado, con los mismos efectos secundarios que ocurren en el mismo orden, como la evaluación del expresión(a) && ((b) && (c))
.- Cada operando del operador condicional y debe ser de tipo
boolean
oBoolean
, o se produce un error en tiempo de compilación.- El tipo de expresión condicional es siempre
boolean
.- En tiempo de ejecución, la expresión del operando de la izquierda se evalúa primero; si el resultado tiene un tipo
Boolean
, está sujeto a la conversión de unboxing ( §5.1.8 ).- Si el valor resultante es
false
, el valor de la expresión condicional y esfalse
y la expresión del operando de la derecha no se evalúa.- Si el valor del operando de la izquierda es
true
, entonces se evalúa la expresión de la mano derecha; si el resultado tiene un tipoBoolean
, está sujeto a la conversión de unboxing ( §5.1.8 ). El valor resultante se convierte en el valor de la expresión condicional.- Por lo tanto,
&&
calcula el mismo resultado que&
en operandosboolean
. Solo difiere en que la expresión del operando de la derecha se evalúa condicionalmente en lugar de siempre.
Conditional-O tiene las siguientes propiedades:
- El operador condicional u operador es sintácticamente de asociación izquierda (se agrupa de izquierda a derecha).
- El operador condicional u operador es totalmente asociativo con respecto a los efectos secundarios y el valor del resultado. Es decir, para cualquier expresión
a
,b
,c
, evaluación de la expresión((a) || (b)) || (c)
((a) || (b)) || (c)
produce el mismo resultado, con los mismos efectos secundarios que ocurren en el mismo orden, como la evaluación de la expresión(a) || ((b) || (c))
(a) || ((b) || (c))
.- Cada operando del operador condicional u operador debe ser de tipo
boolean
oBoolean
, o se produce un error en tiempo de compilación.- El tipo de expresión condicional es siempre
boolean
.- En tiempo de ejecución, la expresión del operando de la izquierda se evalúa primero; si el resultado tiene un tipo
Boolean
, está sujeto a la conversión de unboxing ( §5.1.8 ).- Si el valor resultante es
true
, el valor de la expresión condicional estrue
y la expresión del operando de la derecha no se evalúa.- Si el valor del operando de la izquierda es
false
, entonces se evalúa la expresión de la mano derecha; si el resultado tiene un tipoBoolean
, está sujeto a la conversión de unboxing ( §5.1.8 ). El valor resultante se convierte en el valor de la expresión condicional.- Por lo tanto,
||
calcula el mismo resultado que|
en operandosboolean
oBoolean
. Solo difiere en que la expresión del operando de la derecha se evalúa condicionalmente en lugar de siempre.
En resumen, como @JohnMeagher ha señalado repetidamente en los comentarios, &
y |
son, de hecho, operadores booleanos que no son de cortocircuito en el caso específico de que los operandos sean boolean
o Boolean
. Con buenas prácticas (es decir, sin efectos secundarios), esta es una diferencia menor. Sin embargo, cuando los operandos no son boolean
o Boolean
, los operadores se comportan de manera muy diferente: en modo bit y las operaciones lógicas simplemente no se comparan bien con el alto nivel de programación de Java.
La diferencia básica entre ellos es que | primero convierte los valores a binarios y luego realiza el bit o la operación. Mientras tanto, || no convierte los datos en binarios y solo ejecuta la expresión o en su estado original.
int two = -2; int four = -4;
result = two | four; // bitwise OR example
System.out.println(Integer.toBinaryString(two));
System.out.println(Integer.toBinaryString(four));
System.out.println(Integer.toBinaryString(result));
Output:
11111111111111111111111111111110
11111111111111111111111111111100
11111111111111111111111111111110
Leer más: http://javarevisited.blogspot.com/2015/01/difference-between-bitwsie-and-logical.html#ixzz45PCxdQhk
1). (Expresión1 | expresión2), | el operador evaluará expression2 independientemente de si el resultado de expression1 es verdadero o falso.
Ejemplo:
class Or
{
public static void main(String[] args)
{
boolean b=true;
if (b | test());
}
static boolean test()
{
System.out.println("No short circuit!");
return false;
}
}
2). (Expresión1 || expresión2), || el operador no evaluará expression2 si expression1 es verdadero.
Ejemplo:
class Or
{
public static void main(String[] args)
{
boolean b=true;
if (b || test())
{
System.out.println("short circuit!");
}
}
static boolean test()
{
System.out.println("No short circuit!");
return false;
}
}