¿El operador Java & = aplica & o &&?

139

Asumiendo

boolean a = false;

Me preguntaba si hacer:

a &= b; 

es equivalente a

a = a && b; //logical AND, a is false hence b is not evaluated.

o por otro lado significa

a = a & b; //Bitwise AND. Both a and b are evaluated.
pakore
fuente

Respuestas:

146

De la especificación del lenguaje Java - 15.26.2 Operadores de asignación compuesta .

Una expresión de asignación compuesta de la forma E1 op= E2es equivalente a E1 = (T)((E1) op (E2)), donde Tes el tipo de E1, excepto que E1se evalúa solo una vez.

Entonces a &= b;es equivalente a a = a & b;.

(En algunos usos, la conversión de tipos marca una diferencia en el resultado, pero en este btiene que ser booleany la conversión de tipos no hace nada).

Y, para el registro, a &&= b;no es válido Java. No hay &&=operador


En la práctica, hay poca diferencia semántica entre a = a & b;y a = a && b;. (Si bes una variable o una constante, el resultado será el mismo para ambas versiones. Solo hay una diferencia semántica cuando bhay una subexpresión que tiene efectos secundarios. En el &caso, el efecto secundario siempre ocurre. &&caso ocurre dependiendo del valor de a.)

Por el lado del rendimiento, la compensación es entre el costo de la evaluación by el costo de una prueba y una rama del valor de a, y el ahorro potencial de evitar una asignación innecesaria a a. El análisis no es sencillo, pero a menos que el costo de calcular bno sea trivial, la diferencia de rendimiento entre las dos versiones es demasiado pequeña para que valga la pena considerarla.

Stephen C
fuente
Su párrafo "en la práctica" es engañoso. La única razón para usar & over && es calcular la subexpresión no trivial en "b"
AlexP
Aclarado (De hecho, la trivialidad realmente no entra en juego.)
Stephen C
51

ver 15.22.2 del JLS . Para operandos booleanos, el &operador es booleano, no bit a bit. La única diferencia entre &&y &para los operandos booleanos es que &&está en cortocircuito (lo que significa que el segundo operando no se evalúa si el primer operando se evalúa como falso).

Así, en su caso, si bes una, primitivo a = a && b, a = a & by a &= btodos hacen lo mismo.

estofado
fuente
2
Entonces (a & = b;) no se cortocircuitará si b es una llamada al método? ¿hay algo como un operador "&& ="?
is7s
2
Parece que esto no responde la pregunta; el OP ya sabía sobre cortocircuitos.
O Mapper
21

Es el último:

a = a & b;
Philippe Leybaert
fuente
0

Aquí hay una manera simple de probarlo:

public class OperatorTest {     
    public static void main(String[] args) {
        boolean a = false;
        a &= b();
    }

    private static boolean b() {
        System.out.println("b() was called");
        return true;
    }
}

La salida es b() was called, por lo tanto, se evalúa el operando de la derecha.

Entonces, como ya lo mencionaron otros, a &= bes lo mismo que a = a & b.

usuario7291698
fuente
-2

Encontré una situación similar usando booleanos donde quería evitar llamar a b () si a ya era falso.

Esto funcionó para mí:

a &= a && b()
Daniel Testa
fuente
25
Para evitar redundancias (aún permitiendo cortocircuitos), simplemente puede escribir a=a&&b().
Unai Vivi