Czy operator Java & = ma zastosowanie & czy &&?

139

Zarozumiały

boolean a = false;

Zastanawiałem się, czy robię:

a &= b; 

jest równa

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

albo z drugiej strony to znaczy

a = a & b; //Bitwise AND. Both a and b are evaluated.
pakore
źródło

Odpowiedzi:

146

Ze specyfikacji języka Java - 15.26.2 złożone operatory przypisania .

Wyrażenie przypisania złożonego formularza E1 op= E2jest równoważne z E1 = (T)((E1) op (E2)), gdzie Tjest typem E1, z wyjątkiem tego, że E1jest oceniane tylko raz.

Więc a &= b;jest równoważne a = a & b;.

(W niektórych zastosowaniach rzutowanie typów ma wpływ na wynik, ale w tym bmusi być, booleana rzutowanie typu nic nie robi).

I dla przypomnienia, a &&= b;nie jest to poprawna Java. Nie ma &&=operatora.


W praktyce istnieje niewielka różnica semantyczna między a = a & b;i a = a && b;. (Jeśli bjest to zmienna lub stała, wynik będzie taki sam dla obu wersji. Jest tylko semantyczna różnica, gdy bistnieje podwyrażenie, które ma skutki uboczne. W takim &przypadku efekt uboczny występuje zawsze. &&przypadku występuje w zależności od wartości a.)

Po stronie wydajności kompromis jest między kosztem oceny ba kosztem testu i gałęzi wartości a, a potencjalnymi oszczędnościami wynikającymi z uniknięcia niepotrzebnego przypisywania do a. Analiza nie jest prosta, ale o ile koszt obliczeń bnie jest nietrywialny, różnica w wydajności między tymi dwiema wersjami jest zbyt mała, aby warto ją rozważyć.

Stephen C.
źródło
Twój akapit „w praktyce” wprowadza w błąd. Jedynym powodem użycia & over && jest obliczenie nietrywialnego
wyrażenia podrzędnego
Wyjaśniono. (W rzeczywistości trywialność tak naprawdę nie wchodzi w grę.)
Stephen C
51

patrz 15.22.2 JLS . W przypadku operandów logicznych &operator jest logiczny, a nie bitowy. Jedyną różnicą między &&i &dla operandów boolowskich jest to, &&że są one zwarte (co oznacza, że ​​drugi operand nie jest oceniany, jeśli pierwszy argument ma wartość false).

Tak więc w przypadku, jeśli bjest prymitywny a = a && b, a = a & bi a &= bwszystko zrobić to samo.

gulasz
źródło
2
Więc (a & = b;) nie spowoduje zwarcia, jeśli b jest wywołaniem metody? czy istnieje coś takiego jak operator „&& =”?
is7s
2
Wydaje się, że to nie odpowiada na pytanie; OP wiedział już o zwarciu.
LUB Mapper
21

To ostatnia:

a = a & b;
Philippe Leybaert
źródło
0

Oto prosty sposób, aby to przetestować:

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;
    }
}

Wynik jest b() was called, dlatego wartościowany jest prawy operand.

Tak więc, jak już wspominali inni, a &= bjest taki sam jak a = a & b.

user7291698
źródło
-2

Natknąłem się na podobną sytuację, używając wartości logicznych, w których chciałem uniknąć wywołania b (), jeśli a było już fałszywe.

To zadziałało dla mnie:

a &= a && b()
Daniel Testa
źródło
25
Aby uniknąć nadmiarowości (nadal dopuszczających zwarcia), możesz po prostu napisać a=a&&b().
Unai Vivi