Что означает «| =»? (оператор равных труб)

249

Я попытался выполнить поиск с помощью Google Search и Stack Overflow, но он не дал никаких результатов. Я видел это в коде библиотеки с открытым исходным кодом:

Notification notification = new Notification(icon, tickerText, when);
notification.defaults |= Notification.DEFAULT_SOUND;
notification.defaults |= Notification.DEFAULT_VIBRATE;

Что значит "| =" ( pipe equal operator)?

wtsang02
источник
4
Интересно, pipe equal operatorне поможет ли поиск людей что-то подобное этому вопросу или какой-либо другой документации по этой теме.
Денис Сегюре
10
@EJP вы, ребята, говорите об этих документах . Это ясно говорит, что у документов нет документации об использовании этого.
wtsang02
36
Если вы не знали, что он называется труба равным, действительно трудно найти, не спросив кого-то.
ataulm
@ataulm действительно потратил некоторое время на поиски в интернете, чтобы придумать термин, vertical barкоторый наконец привел меня сюда.
Рутер
1
Возможный дубликат того, что делает оператор | = в Java?
poring91

Ответы:

323

|=читает так же, как +=.

notification.defaults |= Notification.DEFAULT_SOUND;

такой же как

notification.defaults = notification.defaults | Notification.DEFAULT_SOUND;

где | - побитовый оператор ИЛИ

Все операторы упоминаются здесь .

Используется побитовый оператор, потому что, как правило, эти константы позволяют int переносить флаги.

Если вы посмотрите на эти константы, вы увидите, что они имеют две степени:

public static final int DEFAULT_SOUND = 1;
public static final int DEFAULT_VIBRATE = 2; // is the same than 1<<1 or 10 in binary
public static final int DEFAULT_LIGHTS = 4; // is the same than 1<<2 or 100 in binary

Таким образом, вы можете использовать побитовое ИЛИ, чтобы добавить флаги

int myFlags = DEFAULT_SOUND | DEFAULT_VIBRATE; // same as 001 | 010, producing 011

так

myFlags |= DEFAULT_LIGHTS;

просто означает, что мы добавляем флаг.

И симметрично, мы проверяем, установлен ли флаг, используя &:

boolean hasVibrate = (DEFAULT_VIBRATE & myFlags) != 0;
Денис Сегюре
источник
2
Так же, как j += 1;это так же, как j = j + 1;.
Дэвид Шварц
1
@ARS: Я не могу придумать контрпример в Java (может быть, если jесть volatile?), Но я поверю на слово.
Дэвид Шварц
6
@DavidSchwartz Посмотрите это
arshajii
2
boolean hasVibrate = DEFAULT_VIBRATE & myFlags;- Вы можете перевести с intна booleanподобное в Java? Это было бы допустимо в C, но я думал, что в Java это должно было быть написано какboolean hasVibrate = ((DEFAULT_VIBRATE & myFlags) == DEFAULT_VIBRATE);
BlueRaja - Danny Pflughoeft
1
@DavidSchwartz Ух ты, это сравнение +=наконец помогло мне понять это. Спасибо!
C4d
39

У вас уже есть достаточный ответ на ваш вопрос. Но, может быть, мой ответ поможет вам больше о|= бинарных операторах.

Я пишу таблицу для побитовых операторов :
следующие действительны:

----------------------------------------------------------------------------------------
Operator   Description                                   Example
----------------------------------------------------------------------------------------
|=        bitwise inclusive OR and assignment operator   C |= 2 is same as C = C | 2
^=        bitwise exclusive OR and assignment operator   C ^= 2 is same as C = C ^ 2
&=        Bitwise AND assignment operator                C &= 2 is same as C = C & 2
<<=       Left shift AND assignment operator             C <<= 2 is same as C = C << 2
>>=       Right shift AND assignment operator            C >>= 2 is same as C = C >> 2  
----------------------------------------------------------------------------------------

Обратите внимание, что все операторы являются бинарными операторами.

Также обратите внимание: (для пунктов ниже я хотел бы добавить свой ответ)

  • >>>является побитовым оператором в Java, который называется беззнаковым сдвигом
    но >>>=не оператор в Java. >>> = оператор

  • ~является битовым дополнением бит 0 to 1 and 1 to 0(Унарный оператор), но ~=не оператор.

  • Кроме того, !Called Logical NOT Operator, но !=проверяет, равны ли значения двух операндов или нет, если значения не равны, условие становится истинным. например (A != B) is true. где как A=!Bозначает, если Bесть, trueто Aстать false(и если Bесть, falseто Aстать true).

примечание: |не называется pipe, вместо этого вызывается OR, труба - это терминология оболочки, передающая один процесс следующему.

Грижеш Чаухан
источник
9
У меня сложилось впечатление, что «труба» - это имя персонажа, отсюда и появился термин «оболочка». Но, глядя на Википедию, она на самом деле называется «вертикальная черта», а «труба» специфична для команд оболочки. Просто хотел сказать спасибо за добавление этого примечания!
Калеб Бринкман
18

Я искал ответ о том, что |=делает в Groovy, и, хотя ответы выше верны, они не помогли мне понять определенный фрагмент кода, на который я смотрел.

В частности, при применении к логической переменной «| =» она будет установлена ​​в значение ИСТИНА, когда в первый раз встречает правдивое выражение с правой стороны, и УДЕРЖИВАЕТ свое значение ИСТИНА для всех последующих вызовов =. Как защелка.

Вот упрощенный пример этого:

groovy> boolean result  
groovy> //------------ 
groovy> println result           //<-- False by default
groovy> println result |= false 
groovy> println result |= true   //<-- set to True and latched on to it
groovy> println result |= false 

Вывод:

false
false
true
true

Редактировать : Почему это полезно?

Рассмотрим ситуацию, когда вы хотите узнать, изменилось ли что-либо на различных объектах, и если да, уведомить кого-нибудь об этих изменениях. Итак, вы должны установить hasChangesлогическое значение и установить его, |= diff (a,b)а затем |= dif(b,c)и т. Д. Вот краткий пример:

groovy> boolean hasChanges, a, b, c, d 
groovy> diff = {x,y -> x!=y}  
groovy> hasChanges |= diff(a,b) 
groovy> hasChanges |= diff(b,c) 
groovy> hasChanges |= diff(true,false) 
groovy> hasChanges |= diff(c,d) 
groovy> hasChanges 

Result: true
dbrin
источник
10
Да, то же самое в Java. Но стоит отметить, что такая операция ИЛИ неy|=expr является коротким замыканием (в отличие от y = y || expr), то есть exprвсегда оценивается. Это не было очевидно для меня в первый раз :) Поэтому важно отметить перед рефакторингом, что замена y|=exprнеy=y||x является семантически эквивалентной в случае, если на exprсамом деле имеет побочные эффекты.
NIA
1
И, учитывая это, в вашем случае с hasChangesэтим, вероятно, было бы лучше предпочесть y=y||xформу, чтобы получить выгоду от короткого замыкания, потому что, когда вы нашли какое-либо изменение, на самом деле не нужно делать последующие сравнения, потому что вы уже знаете ответ. (Особенно важно в реальной ситуации, когда сравниваемые объекты сложны и diffих работа не совсем быстрая)
NIA
@NIA Спасибо за голосование. Да, я согласен с вашей точкой зрения о коротком замыкании.
дбрин
2
@FranklinYu, конечно, не детали реализации. Отсутствие короткого замыкания специально не упоминается в месте, на которое вы ссылаетесь, просто потому, что оно не является особенностью - это стандартное и нормальное поведение для большинства операторов. Особенностью на самом деле является короткое замыкание ||и &&, и в соответствующих разделах 15.23 и 15.24 спецификации этот факт четко заявлен, и это отличие от |и &подчеркивается.
NIA
2
@FranklinYu Так что я думаю , что не нужно было сказать что - то об этом снова ниже в разделе ссылки (15.26.2 «операторов присваивания Compund») только потому , что compond задание не просто всегда без короткого замыкания (есть нет ||=и &&=операторов , которые бы нарушать правила и требовать особого упоминания).
NIA
13

Это сокращение для этого:

notification.defaults = notification.defaults | Notification.DEFAULT_SOUND;

И |это немного мудрый ИЛИ.

Тиль Хельге
источник
3

Примечание: || = не существует. (логично или) Вы можете использовать

y= y || expr; // expr is NOT evaluated if y==true

или

y = expr ? true : y;  // expr is always evaluated.
woens
источник
4
Не совсем полный: вы все еще можете использовать y |= exprс логическими значениями, и он дает тот же результат, yчто и ваши варианты, с важным примечанием, что он не является кратковременным , что означает, что expr всегда вычисляется, даже в случаеy==true
NIA