Що означає "| ="? (оператор рівномірних труб)


249

Я спробував здійснити пошук за допомогою пошуку Google і переповнення стека, але результати не показали. Я бачив це у відкритому коді бібліотеки:

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

Що означає "| =" ( pipe equal operator)?


4
Цікаво, якщо додати щось подібне pipe equal operatorдо цього питання чи будь-яку іншу документацію на цю тему не допоможе людям, які шукають.
Denys Séguret

10
@EJP Ви, хлопці, говорите про ці документи . Це чітко говорить про відсутність у документах документів щодо використання цього.
wtsang02

36
Якщо ви не знали, що це називається трубою рівним, знайти його справді важко, не питаючи когось.
ataulm

@ataulm, дійсно, витратив деякий час на гугл навколо, щоб придумати термін, vertical barякий нарешті привів мене сюди.
ruuter

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 Дивіться це
arhajii

2
boolean hasVibrate = DEFAULT_VIBRATE & myFlags;- Ви можете перевести з intна booleanподібне в Java? Це було б дійсно в C, але я думав, що на Яві це має бути написано як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).

сторона Примітка: |не називається трубою, замість цього називається АБО, труба - це термінологія оболонки, що передає один процес на інший ..


9
У мене було враження, що "труба" - це ім'я персонажа, звідки і походить термін оболонки. Але, дивлячись на Вікіпедію, це насправді називається "вертикальна смуга", а "труба" характерна для команд оболонки. Просто хотів сказати спасибі за додавання цієї бічної записки!
Caleb Brinkman

18

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

Зокрема, при застосуванні до булевої змінної "| =" встановить її в TRUE, коли він вперше зіткнеться з правдивим виразом праворуч і утримує значення TRUE для всіх | = наступних викликів. Як засувка.

Ось спрощений приклад цього:

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

10
Так, те саме стосується і Java. Але варто відзначити, що така АБО робота неy|=expr є коротким замиканням (на відміну від y = y || expr), тобто exprзавжди оцінюється. Для мене це було не очевидно вперше :) Тому перед рефакторингом важливо зазначити, що заміна y|=exprнеy=y||x є семантично еквівалентною, якщо exprнасправді є побічні ефекти.
NIA

1
І, маючи це на увазі, в вашому випадку з hasChangesним буде , ймовірно , краще віддати перевагу y=y||xформу вигоди від короткого ciruit, тому що , коли ви знайшли будь - яких змін це не на самому ділі потрібно робити susequent , тому що ви подивитися відмінності вже знаєте відповідь. (Особливо важливо в реальній життєвій ситуації, коли порівнюються предмети складні, і diffїх не дуже швидко)
NIA

@NIA Дякую за голос Так, я погоджуюся з вашою думкою про коротке замикання.
дбрин

2
@FranklinYu, звичайно, не деталізація реалізації. Некоротке замикання конкретно не згадується в тому місці, про яке ви посилаєтесь, лише тому, що це не особливість - це поведінка за замовчуванням і нормальна поведінка для більшості операторів. Особливістю є фактично короткість ||і &&, відповідно, у відповідних розділах 15.23 та 15.24 специфікації цей факт чітко задекларований, і ця різниця від |та &підкреслена.
NIA

2
@FranklinYu Тому я думаю, що не потрібно було щось про це повторювати нижче нижче в розділі, на який ви посилалися (15.26.2 "Оператори присвоєння обчислень") лише тому, що призначення композицій просто завжди не є коротким замиканням (немає ||=і &&=операторів, які б порушити правило і вимагати спеціального згадування).
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.

4
Не зовсім повно: ви все одно можете використовувати y |= exprз булевими, і це дає такий же результат, yяк і ваші варіанти, при цьому важлива примітка, що вона не є короткою , а значить, що expr завжди оцінюється, навіть у випадкуy==true
NIA
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.