Co oznacza „| =”? (operator równości rur)


249

Próbowałem szukać za pomocą wyszukiwarki Google i przepełnienia stosu, ale nie przyniosło to żadnych wyników. Widziałem to w kodzie biblioteki opensource:

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

Co oznacza „| =” ( pipe equal operator)?


4
Zastanawiam się, czy dodanie czegoś takiego pipe equal operatordo tego pytania lub jakiejkolwiek innej dokumentacji na ten temat nie pomogłoby ludziom w wyszukiwaniu.
Denys Séguret,

10
@EJP wy mówicie o tym docs . To wyraźnie mówi, że dokumentom brakuje dokumentacji na temat korzystania z tego.
wtsang02

36
O ile nie wiesz, że to się nazywa fajka, naprawdę trudno jest szukać bez pytania kogoś.
ataulm

@ataulm rzeczywiście, spędziłem trochę czasu na wyszukiwaniu w Internecie, aby znaleźć termin, vertical barktóry w końcu mnie tu doprowadził.
ruuter

Odpowiedzi:


323

|=czyta tak samo jak +=.

notification.defaults |= Notification.DEFAULT_SOUND;

jest taki sam jak

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

gdzie |jest bitowym operatorem LUB.

Wszystkie operatory są tutaj wymienione .

Używany jest operator bitowy, ponieważ, jak to często bywa, te stałe umożliwiają int przenoszenie flag.

Jeśli spojrzysz na te stałe, zobaczysz, że mają potęgę dwóch:

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

Możesz więc użyć bitowej LUB do dodania flag

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

więc

myFlags |= DEFAULT_LIGHTS;

oznacza po prostu, że dodajemy flagę.

I symetrycznie testujemy flagę ustawioną za pomocą &:

boolean hasVibrate = (DEFAULT_VIBRATE & myFlags) != 0;

2
Tak samo jak j += 1;jest to samo j = j + 1;.
David Schwartz,

1
@ARS: Nie mogę wymyślić kontrprzykładu w Javie (może jeśli jjest volatile?), Ale uwierzę ci na słowo.
David Schwartz

6
@DavidSchwartz Zobacz to
arshajii

2
boolean hasVibrate = DEFAULT_VIBRATE & myFlags;- można tłumaczyć ze intdo booleantakiego w Java? To byłoby ważne w C, ale pomyślałem, że w Javie musi być napisany jakoboolean hasVibrate = ((DEFAULT_VIBRATE & myFlags) == DEFAULT_VIBRATE);
BlueRaja - Danny Pflughoeft

1
@DavidSchwartz Wow, to porównanie z +=ostatecznie pomogło mi zrozumieć. Dzięki!
C4d

39

Masz już wystarczającą odpowiedź na swoje pytanie. Ale może moja odpowiedź pomoże ci bardziej na temat |=operatorów binarnych.

Piszę tabelę dla operatorów bitowych :
Następujące są poprawne:

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

Uwaga: wszyscy operatorzy są operatorami binarnymi.

Również uwaga: (poniżej punktów chciałem dodać moją odpowiedź)

  • >>>jest bitowym operatorem w Javie o nazwie Przesunięcie niepodpisane
    ale >>>=nie operator w Javie. >>> = operator

  • ~to bitowe uzupełnienie bitowe 0 to 1 and 1 to 0(operator jednoargumentowy), ale ~=nie operator.

  • Dodatkowo !nazywany logicznym operatorem NOT, ale !=sprawdza, czy wartość dwóch argumentów jest równa, czy nie, jeśli wartości nie są równe, wówczas warunek staje się prawdziwy. np (A != B) is true. gdzie jako A=!Bśrodek jeśli Bjest truenastępnie Asię false(jeśli Bjest falsewtedy Astać true).

uwaga dodatkowa: |nie jest nazywana potokiem, a zamiast niej OR, potok jest terminologią powłoki przenoszącą jeden proces do następnego ..


9
Miałem wrażenie, że „fajka” to nazwa postaci, stąd też pochodzi nazwa powłoki. Ale patrząc na Wikipedię, tak naprawdę nazywa się to „pionowym paskiem”, a „rura” jest specyficzna dla poleceń powłoki. Chciałem tylko podziękować za dodanie tej notatki dodatkowej!
Caleb Brinkman

18

Szukałem odpowiedzi na pytanie, co |=robi Groovy i chociaż powyższe odpowiedzi są prawidłowe, nie pomogły mi zrozumieć konkretnego fragmentu kodu, na który patrzyłem.

W szczególności, po zastosowaniu do zmiennej logicznej „| =” ustawi ją na PRAWDA, kiedy po raz pierwszy napotka prawdziwe wyrażenie po prawej stronie i zatrzyma swoją PRAWDZIWĄ wartość dla wszystkich | = kolejnych wywołań. Jak zatrzask.

Oto uproszczony przykład tego:

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 

Wynik:

false
false
true
true

Edycja : Dlaczego to jest przydatne?

Rozważ sytuację, w której chcesz wiedzieć, czy coś się zmieniło na różnych obiektach, a jeśli tak, powiadom jedną ze zmian. Tak więc hasChangesustawilibyśmy wartość logiczną, |= diff (a,b)a następnie |= dif(b,c)itd. Oto krótki przykład:

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
Tak, to samo dotyczy Java. Warto jednak zauważyć, że taka operacja OR niey|=expr powoduje zwarcia (w przeciwieństwie do y = y || expr), co oznacza, że exprzawsze oceniana. Nie było to dla mnie oczywiste po raz pierwszy :) Dlatego przed refaktoryzacją należy zauważyć, że zamiana y|=exprniey=y||x jest semantycznie równoważna w przypadku, gdy exprrzeczywiście ma skutki uboczne.
NIA

1
I mając to na uwadze, w danym przypadku z hasChangesniego będzie zapewne lepiej byłoby wolą y=y||xformę do korzystania z krótkim ciruit, bo kiedy znaleziono żadnych zmian nie jest to rzeczywiście potrzebne, aby zrobić susequent dyferencjału bo znasz już odpowiedź. (Jest to szczególnie ważne w rzeczywistej sytuacji, gdy porównywane obiekty są skomplikowane, a diffich wprowadzanie nie jest dość szybkie)
NIA

@NIA Dziękujemy za głosowanie w górę. Tak, zgadzam się z twoją opinią na temat zwarcia.
dbrin

2
@FranklinYu oczywiście nie szczegóły dotyczące implementacji. Brak zwarć nie jest specjalnie wymieniony w miejscu, do którego się odwołujesz, tylko dlatego, że nie jest to osobliwość - jest to domyślne i normalne zachowanie większości operatorów. Osobliwością jest rzeczywiście krótki circutiness od ||i &&, w odpowiednich rozdziałach 15.23 i 15.24 specyfikacji fakt ten jest wyraźnie oświadczył i ta różnica z |i &jest podkreślona.
NIA

2
@FranklinYu Więc myślę, że nie było potrzeby mówić o tym ponownie w poniższej części (15.26.2 „Operatorzy przypisania Compund”) tylko dlatego, że przypisania Compond są po prostu zawsze niezawarte (nie ma operatorów ||=i &&=operatorów, którzy by złamać zasadę i wymagać specjalnego wzmianki).
NIA

13

Jest to skrócenie tego:

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

I |jest nieco mądry LUB.



3

Uwaga: || = nie istnieje. (logiczne lub) Możesz użyć

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

lub

y = expr ? true : y;  // expr is always evaluated.

4
Niezupełnie kompletny: nadal możesz używać y |= exprz wartościami logicznymi i daje to ten sam wynik, yco twoje warianty, z ważną uwagą, że nie jest krótki , co oznacza, że ​​wyrażenie jest zawsze oceniane, nawet w przypadkuy==true
NIA
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.