Чи застосовує оператор Java & = & & &&?


139

Припускаючи

boolean a = false;

Мені було цікаво, чи роблю:

a &= b; 

еквівалентно

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

або з іншого боку це означає

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

Відповіді:


146

Із специфікації мови Java - 15.26.2 Оператори призначення складних сполук .

Вираження складної форми форми E1 op= E2еквівалентно E1 = (T)((E1) op (E2)), де Tє тип E1, за винятком того, що E1оцінюється лише один раз.

Так що a &= b;еквівалентно a = a & b;.

(У деяких звичаях кастинг типів змінює результат, але в цьому bвін повинен бути, booleanа тип-лиття нічого не робить.)

І, для запису, a &&= b;недійсна Java. &&=Оператора немає .


На практиці семантична різниця між a = a & b;та a = a && b;. (Якщо bце змінна чи константа, результат буде однаковим для обох версій. Є лише семантична різниця, коли bє субэкспрессия, яка має побічні ефекти. У &випадку, побічний ефект завжди виникає. &&якщо вона виникає залежно від значення a.)

З боку продуктивності, компроміс полягає у вартості оцінювання bта вартості тесту та філії вартості aта потенційному заощадженні, щоб уникнути зайвого призначення a. Аналіз не є прямолінійним, але, якщо вартість розрахунку bнетривіальна, різниця в продуктивності між двома версіями занадто мала, щоб її варто було б врахувати.


Ваш пункт "на практиці" вводить в оману. Єдина причина використовувати & over && - це обчислити нетривіальну субекспресію в "b"
AlexP

Уточнено. (Насправді, дрібниця насправді не входить у неї.)
Стівен C

51

див. 15.22.2 JLS . Для булевих операндів &оператор булів, а не порозрядно. Єдина відмінність між &&та &булевими операндами полягає в тому, що для &&нього коротке замикання (це означає, що другий операнд не оцінюється, якщо перший операнд оцінюється як хибний).

Так що в вашому випадку, якщо bце примітивно, a = a && b, a = a & bі a &= bвсе роблять те ж саме.


2
Тож (a & = b;) не буде короткого замикання, якщо b - виклик методу? чи є щось на зразок оператора "&& ="?
is7s

2
Здається, це не відповідає на питання; ОП вже знала про коротке замикання.
АБО Mapper


0

Ось простий спосіб перевірити це:

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

Вихід є b() was called, тому оцінюється правий операнд.

Отже, як уже згадували інші, a &= bте саме, що a = a & b.


-2

Я натрапив на подібну ситуацію, використовуючи булеві, де я хотів уникнути виклику b (), якщо a вже було помилковим.

Це працювало для мене:

a &= a && b()

25
Щоб уникнути надмірностей (все ж допускаючи коротке замикання), ви можете просто написати a=a&&b().
Унай Віві
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.