Diferencias en operadores booleanos: & vs && y | vs ||

Sé las reglas para && y || pero que son & y | ? Por favor explícame esto con un ejemplo.

Esos son los operadores OR a nivel de bit AND y bitwise.

 int a = 6; // 110 int b = 4; // 100 // Bitwise AND int c = a & b; // 110 // & 100 // ----- // 100 // Bitwise OR int d = a | b; // 110 // | 100 // ----- // 110 System.out.println(c); // 4 System.out.println(d); // 6 

Gracias a Carlos por señalar la sección apropiada en Java Language Spec ( 15.22.1 , 15.22.2 ) con respecto a los diferentes comportamientos del operador en función de sus entradas.

De hecho, cuando ambas entradas son booleanas, los operadores se consideran operadores lógicos booleanos y se comportan de manera similar a los operadores Conditional-And ( && ) y Conditional-Or ( || ), excepto por el hecho de que no provocan un cortocircuito. siguiente es seguro:

 if((a != null) && (a.something == 3)){ } 

Esto no es:

 if((a != null) & (a.something == 3)){ } 

Creo que estás hablando del significado lógico de ambos operadores, aquí tienes un resumen de la tabla:

 boolean a, b; Operation Meaning Note --------- ------- ---- a && b logical AND short-circuiting a || b logical OR short-circuiting a & b boolean logical AND not short-circuiting a | b boolean logical OR not short-circuiting a ^ b boolean logical exclusive OR !a logical NOT short-circuiting (x != 0) && (1/x > 1) SAFE not short-circuiting (x != 0) & (1/x > 1) NOT SAFE 

Sé que hay muchas respuestas aquí, pero todas parecen un poco confusas. Entonces, después de investigar un poco de la guía de estudio de Oracle Oracle, he llegado a tres escenarios diferentes de cuándo usar && o &. Los tres escenarios son AND lógico , AND a nivel de bit y AND AND booleano .

Lógico Y: lógico Y (también conocido como Y condicional) utiliza el operador && . Su significado es cortocircuitado: si el operando de la izquierda es falso, entonces el operando de la derecha no será evaluado.
Ejemplo:

 int x = 0; if (false && (1 == ++x) { System.out.println("Inside of if"); } System.out.println(x); // "0" 

En el ejemplo anterior, el valor impreso en la consola de x será 0, porque el primer operando en la instrucción if es falso, por lo tanto, java no tiene necesidad de calcular (1 == ++ x), por lo tanto, x no se computará.

Bitwise AND: Bitwise AND usa el operador & . Se usa para preformar una operación bit a bit en el valor. Es mucho más fácil ver lo que está pasando al observar la operación en números binarios ex:

 int a = 5; // 5 in binary is 0101 int b = 12; // 12 in binary is 1100 int c = a & b; // bitwise & preformed on a and b is 0100 which is 4 

Como se puede ver en el ejemplo, cuando las representaciones binarias de los números 5 y 12 están alineadas, entonces, un Y preformado a nivel de bit solo producirá un número binario donde el mismo dígito en ambos números tenga un 1. Por lo tanto, 0101 y 1100 == 0100. Que en decimal es 5 y 12 == 4.

Boolean AND: ahora el operador booleano AND se comporta de manera similar y diferente tanto con el AND a nivel de bit como con el Y lógico. Me gusta pensar que se está formateando AND a nivel de bit entre dos valores booleanos (o bits), por lo tanto usa & operador. Los valores booleanos también pueden ser el resultado de una expresión lógica.

Devuelve un valor verdadero o falso, al igual que el AND lógico, pero a diferencia del AND lógico y no está cortocircuitado. La razón es que, para que preforma ese Y a nivel de bit, debe conocer el valor de los operandos izquierdo y derecho. Aquí hay un ex:

 int x = 0; if (false & (1 == ++x) { System.out.println("Inside of if"); } System.out.println(x); //"1" 

Ahora cuando se ejecute esa instrucción if, se ejecutará la expresión (1 == ++ x), aunque el operando de la izquierda sea falso. Por lo tanto, el valor impreso para x será 1 porque se incrementó.

Esto también se aplica a OR lógico (||), a nivel de bit OR (|), y booleano O (|) Espero que esto aclare algo de confusión.

Los operadores && y || están en cortocircuito, lo que significa que no evaluarán su expresión de la mano derecha si el valor de la expresión de la mano izquierda es suficiente para determinar el resultado.

& y | proporciona el mismo resultado que el && y || operadores. La diferencia es que siempre evalúan ambos lados de la expresión donde como && y || deje de evaluar si la primera condición es suficiente para determinar el resultado.

En Java, los operadores individuales &, |, ^,! depende de los operandos. Si ambos operandos son enteros, entonces se realiza una operación bit a bit. Si ambos son booleanos, se realiza una operación “lógica”.

Si ambos operandos no coinciden, se produce un error de tiempo de comstackción.

Los operadores dobles &&, || comportarse de manera similar a sus contrapartes individuales, pero ambos operandos deben ser expresiones condicionales, por ejemplo:

if ((a <0) && (b <0)) {...} o similarmente, if ((a <0) || (b <0)) {...}

fuente: java programming lang 4th ed

& y | son operadores bit a bit en tipos integrales (por ejemplo, int ): http://download.oracle.com/javase/tutorial/java/nutsandbolts/op3.html

&& y || opere solo en booleanos (y en cortocircuito, como ya han dicho otras respuestas).

Tal vez pueda ser útil saber que los operadores OR a nivel de bit AND y bit a bit siempre se evalúan antes de Y condicional y CONdicional O se usan en la misma expresión.

 if ( (1>2) && (2>1) | true) // false! 

&&; || son operadores lógicos …. cortocircuito

&; | son operadores lógicos booleanos …. No cortocircuito

Pasando a las diferencias en la ejecución de las expresiones. Los operadores bit a bit evalúan ambos lados independientemente del resultado del lado izquierdo. Pero en el caso de evaluar expresiones con operadores lógicos, la evaluación de la expresión de la mano derecha depende de la condición de la mano izquierda.

Por ejemplo:

 int i = 25; int j = 25; if(i++ < 0 && j++ > 0) System.out.println("OK"); System.out.printf("i = %d ; j = %d",i,j); 

Esto imprimirá i = 26; j = 25, como la primera condición es falsa, la condición de la mano derecha se omite ya que el resultado es falso de todos modos, independientemente de la condición del lado derecho. (Cortocircuito)

 int i = 25; int j = 25; if(i++ < 0 & j++ > 0) System.out.println("OK"); System.out.printf("i = %d ; j = %d",i,j); 

Pero, esto imprimirá i = 26; j = 26,

Si se evalúa una expresión que involucra al operador booleano & , se evalúan ambos operandos. Luego, el operador & se aplica al operando.

Cuando se evalúa una expresión que involucra el operador && , se evalúa el primer operando. Si el primer operando se evalúa como falso, se omite la evaluación del segundo operando.

Si el primer operando devuelve un valor verdadero, se evalúa el segundo operando. Si el segundo operando devuelve un valor de verdadero, entonces el operador && se aplica al primer y segundo operandos.

Similar para | y ||.

Mientras que la diferencia básica es que & se usa para operaciones bit a bit, principalmente en long , int o byte donde se puede usar para una especie de máscara, los resultados pueden diferir incluso si lo usa en lugar de && lógico.

La diferencia es más notable en algunos escenarios:

  1. Evaluar algunas de las expresiones lleva mucho tiempo
  2. La evaluación de una de las expresiones se puede hacer solo si la anterior fue verdadera
  3. Las expresiones tienen algún efecto secundario (intencionado o no)

El primer punto es bastante sencillo, no causa errores, pero lleva más tiempo. Si tiene varias comprobaciones diferentes en una instrucción condicional, coloque aquellas que son más baratas o más propensas a fallar a la izquierda.

Para el segundo punto, mira este ejemplo:

 if ((a != null) & (a.isEmpty())) 

Esto falla para null , ya que la evaluación de la segunda expresión produce una NullPointerException . El operador lógico && es flojo, si el operando izquierdo es falso, el resultado es falso sin importar el operando correcto.

Ejemplo para el tercer punto: digamos que tenemos una aplicación que usa DB sin disparadores o cascadas. Antes de eliminar un objeto Building, debemos cambiar el edificio de un objeto Department por otro. Digamos también que el estado de la operación se devuelve como un booleano (verdadero = éxito). Entonces:

 if (departmentDao.update(department, newBuilding) & buildingDao.remove(building)) 

Esto evalúa ambas expresiones y, por lo tanto, lleva a cabo la eliminación del edificio incluso si la actualización del departamento falló por alguna razón. Con && , funciona según lo previsto y se detiene después de la primera falla.

En cuanto a a || b a || b , es equivalente a !(!a && !b) , se detiene si a es cierto, no se necesita más explicación.