Применяет ли оператор Java & = & или &&?

142

Предполагая

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.
пакоре
источник

Ответы:

148

Из Спецификации языка 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
Уточнено. (На самом деле, в этом нет ничего необычного.)
Стивен К.
51

см. 15.22.2 JLS . Для булевых операндов &оператор является логическим, а не побитовым. Единственная разница между логическими операндами &&и &для них заключается в том, что &&они закорочены (это означает, что второй операнд не оценивается, если первый операнд принимает значение false).

Так что в вашем случае, если bэто примитивно, a = a && b, a = a & bи a &= bвсе делают то же самое.

тушить
источник
3
Итак, (a & = b;) не будет короткого замыкания, если b - это вызов метода? есть ли что-то вроде оператора "&& ="?
is7s
2
Похоже, это не отвечает на вопрос; ОП уже знал о коротком замыкании.
OR Mapper
22

Это последний:

a = a & b;
Филипп Лейберт
источник
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.

user7291698
источник
-3

Я столкнулся с аналогичной ситуацией с использованием логических значений, когда я хотел избежать вызова b (), если a уже было ложным.

Это сработало для меня:

a &= a && b()
Дэниел Теста
источник
25
Чтобы избежать избыточности (все еще допускающей короткое замыкание), вы можете просто написать a=a&&b().
Унаи Виви