Cortocircuito del operador lógico Java

100

¿Qué conjunto está en cortocircuito y qué significa exactamente que la expresión condicional compleja está en cortocircuito?

public static void main(String[] args) {
  int x, y, z;

  x = 10;
  y = 20;
  z = 30;

  // T T
  // T F
  // F T
  // F F

  //SET A
  boolean a = (x < z) && (x == x);
  boolean b = (x < z) && (x == z);
  boolean c = (x == z) && (x < z);
  boolean d = (x == z) && (x > z);
  //SET B    
  boolean aa = (x < z) & (x == x);
  boolean bb = (x < z) & (x == z);
  boolean cc = (x == z) & (x < z);
  boolean dd = (x == z) & (x > z);

}
Aaron
fuente
4
Vea esta pregunta: stackoverflow.com/questions/7101992/…
Ing

Respuestas:

244

El &&y|| operadores "cortocircuitan", lo que significa que no evalúan el lado derecho si no es necesario.

Los operadores &y |, cuando se utilizan como operadores lógicos, siempre evalúan ambos lados.

Solo hay un caso de cortocircuito para cada operador, y son:

  • false && ...- no es necesario saber cuál es el lado derecho porque el resultado solo puede ser falseindependientemente del valor allí
  • true || ...- no es necesario saber cuál es el lado derecho porque el resultado solo puede ser trueindependientemente del valor allí

Comparemos el comportamiento en un ejemplo simple:

public boolean longerThan(String input, int length) {
    return input != null && input.length() > length;
}

public boolean longerThan(String input, int length) {
    return input != null & input.length() > length;
}

La segunda versión usa el operador sin cortocircuito &y lanzará un NullPointerExceptionif inputis null, pero la primera versión regresará falsesin excepción.

Bohemio
fuente
9
Solo me gustaría extender un poco esta respuesta. El operador & = es una abreviatura de la expresión x = x & y, por lo tanto, NO produce un cortocircuito. Lo mismo ocurre con el operador | =.
Stormcloud
11
Una cosa que me gustaría destacar, | y & son operadores binarios, mientras que && y || son operadores condicionales (lógicos). | y & trabajan en algo más que valores booleanos, mientras que && y || trabajar solo en booleanos.
Un mito
1
No solo no evalúan la expresión en el lado derecho, el código no se ejecuta para que haya algo que evaluar. Este es un punto crítico de comprensión si de lo contrario se produciría un efecto secundario.
mckenzm
@mckenzm ¿Cuál es la diferencia entre evaluado y ejecutado?
Kronen
La ejecución de @Kronen puede resultar en más que la evaluación, y producir un efecto secundario, como una excepción o un retraso, pagaré no relevante para este ejemplo.
mckenzm
9

SET A utiliza operadores booleanos de cortocircuito.

Lo que significa "cortocircuito" en el contexto de los operadores booleanos es que para un conjunto de valores booleanos b1, b2, ..., bn, las versiones de cortocircuito dejarán de evaluarse tan pronto como el primero de estos valores booleanos sea verdadero (|| ) o falso (&&).

Por ejemplo:

// 2 == 2 will never get evaluated because it is already clear from evaluating
// 1 != 1 that the result will be false.
(1 != 1) && (2 == 2)

// 2 != 2 will never get evaluated because it is already clear from evaluating
// 1 == 1 that the result will be true.
(1 == 1) || (2 != 2)
afrischke
fuente
Especifique que este es el caso &&, ||funciona de manera diferente y dejará de evaluarse en el primer operando que devuelva verdadero;)
fge
1
De hecho, para ser realmente completa, todos &&, ||, &y |valorar izquierda a derecha. Para un conjunto de valores booleanos b1, b2, ..., bn, las versiones de cortocircuito dejarán de evaluarse cuando el primero de estos valores booleanos sea verdadero ( ||) o falso (&& ). Bah, el principio está ahí;)
fge
@fge: Sí, tienes razón, por supuesto. Tu definición es más exacta que la mía. He actualizado mi respuesta con la frase de tu comentario. Espero que no te moleste.
afrischke
No se preocupe, el conocimiento no tiene valor si no se comparte.
fge
4

Cortocircuito significa que el segundo operador no será verificado si el primer operador decide el resultado final.

Por ejemplo, la expresión es: Verdadero || Falso

En el caso de ||, todo lo que necesitamos es que uno de los lados sea ​​Verdadero. Entonces, si el lado izquierdo es verdadero, no tiene sentido verificar el lado derecho y, por lo tanto, no se verificará en absoluto.

Del mismo modo, False && True

En el caso de &&, necesitamos que ambos lados sean verdaderos. Entonces, si el lado izquierdo es Falso, no tiene sentido verificar el lado derecho, la respuesta tiene que ser Falso. Y, por tanto, eso no se comprobará en absoluto.

Bhushan
fuente
4
boolean a = (x < z) && (x == x);

Este tipo tendrá un cortocircuito, lo que significa que si se (x < z)evalúa como falso, este último no se evalúa, aserá falso, de lo contrario &&también se evaluará (x == x).

& es un operador bit a bit, pero también un operador booleano AND que no cortocircuita.

Puede probarlos con algo de la siguiente manera (vea cuántas veces se llama al método en cada caso):

public static boolean getFalse() {
    System.out.println("Method");
    return false;
}

public static void main(String[] args) {
    if(getFalse() && getFalse()) { }        
    System.out.println("=============================");        
    if(getFalse() & getFalse()) { }
}
Bhesh Gurung
fuente
-1 Su respuesta sugiere que &es solo un operador bit a bit, pero eso no es cierto. Es también un "o" operador booleano.
Bohemio
@Bohemian: Gracias por avisar. true & falsese evalúa como falso. ¿Puede explicar este "booleano" u "operador"? Puede ser que no entiendo lo que estás tratando de decir.
Bhesh Gurung
Lo siento, quise decir booleano AND, OR¡ no ! true & falsees decir, es una sintaxis válida. -1 eliminado :)
Bohemio
4

En términos sencillos, cortocircuitar significa detener la evaluación una vez que se sabe que la respuesta ya no puede cambiar. Por ejemplo, si está evaluando una cadena de ANDs lógicas y descubre un FALSEen el medio de esa cadena, sabe que el resultado será falso, sin importar cuáles sean los valores del resto de las expresiones en la cadena. Lo mismo ocurre con una cadena de ORs: una vez que descubre a TRUE, sabe la respuesta de inmediato y, por lo tanto, puede omitir la evaluación del resto de las expresiones.

Indicas a Java que quieres un cortocircuito usando en &&lugar de &y en ||lugar de |. El primer conjunto de tu publicación es un cortocircuito.

Tenga en cuenta que esto es más que un intento de ahorrar algunos ciclos de CPU: en expresiones como esta

if (mystring != null && mystring.indexOf('+') > 0) {
    ...
}

cortocircuito significa una diferencia entre el funcionamiento correcto y un bloqueo (en el caso de que mystring sea nulo).

dasblinkenlight
fuente
2

Java proporciona dos operadores booleanos interesantes que no se encuentran en la mayoría de los otros lenguajes informáticos. Estas versiones secundarias de AND y OR se conocen como operadores lógicos de cortocircuito. . Como puede ver en la tabla anterior, el operador OR da como resultado verdadero cuando A es verdadero, sin importar lo que sea B.

De manera similar, el operador AND da como resultado falso cuando A es falso, sin importar lo que sea B. Si usa los formularios ||y &&, en lugar de |y& formas de estos operadores, Java no se molestará en evaluar solo el operando de la derecha. Esto es muy útil cuando el operando de la derecha depende de que el de la izquierda sea verdadero o falso para funcionar correctamente.

Por ejemplo, el siguiente fragmento de código muestra cómo puede aprovechar la evaluación lógica de cortocircuito para asegurarse de que una operación de división será válida antes de evaluarla:

if ( denom != 0 && num / denom >10)

Dado que &&se usa la forma de cortocircuito de AND ( ), no hay riesgo de causar una excepción en tiempo de ejecución de dividir por cero. Si esta línea de código se escribiera usando la &versión única de AND, ambos lados tendrían que ser evaluados, provocando una excepción en tiempo de ejecución cuando denomes cero.

Es una práctica estándar usar las formas de cortocircuito de Y y O en casos que involucran lógica booleana, dejando las versiones de un solo carácter exclusivamente para operaciones bit a bit. Sin embargo, hay excepciones para esta regla. Por ejemplo, considere la siguiente declaración:

 if ( c==1 & e++ < 100 ) d = 100;

Aquí, el uso de un solo &asegura que la operación de incremento se aplicará a esi ces igual a 1 o no.

Dileep Kumar
fuente
2

OR lógico: devuelve verdadero si al menos uno de los operandos se evalúa como verdadero. Ambos operandos se evalúan antes de aplicar el operador OR.

O cortocircuito: - si el operando del lado izquierdo devuelve verdadero, devuelve verdadero sin evaluar el operando del lado derecho.

Dimansha Malrindu
fuente
2

Hay un par de diferencias entre los operadores &y &&. Las mismas diferencias se aplican a |y ||. Lo más importante a tener en cuenta es que &&es un operador lógico que solo se aplica a operandos booleanos, mientras que &es un operador bit a bit que se aplica tanto a tipos enteros como a booleanos.

Con una operación lógica, puede hacer un cortocircuito porque en ciertos casos (como el primer operando de &&ser false, o el primer operando de ||ser true), no necesita evaluar el resto de la expresión. Esto es muy útil para hacer cosas como verificar nullantes de acceder a un archivo o método, y verificar posibles ceros antes de dividir por ellos. Para una expresión compleja, cada parte de la expresión se evalúa de forma recursiva de la misma manera. Por ejemplo, en el siguiente caso:

(7 == 8) || ( (1 == 3) && (4 == 4))

Solo se evaluarán las partes destacadas. Para calcular el ||, primero verifique si 7 == 8es true. Si lo fuera, el lado derecho se omitiría por completo. El lado derecho solo verifica si lo 1 == 3es false. Dado que lo es, 4 == 4no es necesario verificarlo y toda la expresión se evalúa como false. Si el lado izquierdo fuera true, por ejemplo, en 7 == 7lugar de 7 == 8, se omitiría todo el lado derecho porque la ||expresión completa sería trueindependientemente.

Con una operación bit a bit, necesita evaluar todos los operandos porque en realidad solo está combinando los bits. Los booleanos son efectivamente un entero de un bit en Java (independientemente de cómo funcionen los internos), y es solo una coincidencia que pueda hacer cortocircuitos para operadores bit a bit en ese caso especial. La razón por la que no puede cortocircuitar un entero &u |operación general es que algunos bits pueden estar activados y otros desactivados en cualquiera de los operandos. Algo como 1 & 2produce cero, pero no tiene forma de saberlo sin evaluar ambos operandos.

Físico loco
fuente
1
if(demon!=0&& num/demon>10)

Dado que se usa la forma de cortocircuito de AND (&&), no hay riesgo de causar una excepción en tiempo de ejecución cuando demon es cero.

Árbitro. Java 2 Quinta edición por Herbert Schildt

Nitesh Verma
fuente