O que significa "| ="? (operador igual de tubo)

249

Tentei pesquisar usando a Pesquisa do Google e o estouro de pilha, mas ele não apresentou nenhum resultado. Eu já vi isso no código da biblioteca de código-fonte aberto:

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

O que significa "| =" ( pipe equal operator)?

wtsang02
fonte
4
Gostaria de saber se adicionar algo parecido pipe equal operatora esta pergunta ou qualquer outra documentação sobre o tópico não ajudaria as pessoas a pesquisar.
Denys Séguret
10
@EJP vocês estão falando sobre essa documentação ? Diz claramente que a documentação não possui documentação sobre o uso disso.
wtsang02
36
A menos que você soubesse que era chamado de pipe igual, é realmente difícil procurar sem perguntar a alguém.
ataulm
@ataulm, de fato, passei algum tempo pesquisando em torno de um termo vertical barque finalmente me levou até aqui.
ruuter
1
Possível duplicata do que o operador | = faz em Java?
poring91

Respostas:

323

|=lê da mesma maneira que +=.

notification.defaults |= Notification.DEFAULT_SOUND;

é o mesmo que

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

onde |é o operador OR bit a bit.

Todos os operadores são referenciados aqui .

Um operador bit a bit é usado porque, como é frequente, essas constantes permitem que um int carregue sinalizadores.

Se você olhar para essas constantes, verá que elas têm poderes de dois:

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

Então você pode usar OR bit a bit para adicionar sinalizadores

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

tão

myFlags |= DEFAULT_LIGHTS;

simplesmente significa que adicionamos uma bandeira.

E simetricamente, testamos que um sinalizador é definido usando &:

boolean hasVibrate = (DEFAULT_VIBRATE & myFlags) != 0;
Denys Séguret
fonte
2
Assim como j += 1;é o mesmo que j = j + 1;.
David Schwartz
1
@ARS: Não consigo pensar em um contra-exemplo em Java (talvez se jfor volatile?), Mas vou aceitar sua palavra.
David Schwartz
6
@DavidSchwartz Veja isto
arshajii 12/01
2
boolean hasVibrate = DEFAULT_VIBRATE & myFlags;- você pode traduzir de intpara booleanassim em Java? Isso seria válido em C, mas eu pensei que em Java tinha que ser escrito comoboolean hasVibrate = ((DEFAULT_VIBRATE & myFlags) == DEFAULT_VIBRATE);
BlueRaja - Danny Pflughoeft
1
@DavidSchwartz Uau, essa comparação com +=finalmente fez o truque para eu entender. Obrigado!
C4d #
39

Você já tem resposta suficiente para sua pergunta. Mas pode ser minha resposta ajudá-lo mais sobre o |=tipo de operadores binários.

Estou escrevendo tabela para operadores bit a bit : A
seguir, são válidos:

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

note que todos os operadores são operadores binários.

Também Nota: (para abaixo pontos que eu queria acrescentar a minha resposta)

  • >>>é um operador bit a bit em Java chamado deslocamento não assinado
    mas >>>=não um operador em Java. >>> = operador

  • ~é bits de complemento bit a bit, 0 to 1 and 1 to 0(operador unário), mas ~=não um operador.

  • Além disso, !chamado operador lógico NÃO, mas !=verifica se o valor de dois operandos é igual ou não, se os valores não são iguais, a condição se torna verdadeira. por exemplo (A != B) is true. onde como A=!Bsignifica se Bé trueentão Ase torna false(e se Bé falseentão Ase torna true).

nota lateral: |não é chamado pipe, em vez disso é chamado OR, pipe é terminologia de shell, transfere um processo para o próximo.

Grijesh Chauhan
fonte
9
Fiquei com a impressão de que "pipe" era o nome do personagem, de onde veio o termo shell. Mas, olhando para a Wikipedia, na verdade é chamado de "barra vertical" e "pipe" é específico dos comandos do shell. Só queria agradecer por adicionar essa nota lateral!
Caleb Brinkman
18

Eu estava procurando uma resposta sobre o que |=faz no Groovy e, embora as respostas acima estejam corretas, elas não me ajudaram a entender um pedaço de código específico que eu estava procurando.

Em particular, quando aplicada a uma variável booleana "| =", ela será configurada como TRUE na primeira vez em que encontrar uma expressão verdadeira no lado direito e manterá seu valor TRUE para todas as chamadas subsequentes. Como uma trava.

Aqui está um exemplo simplificado disso:

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 

Resultado:

false
false
true
true

Edit : Por que isso é útil?

Considere uma situação em que você deseja saber se algo mudou em uma variedade de objetos e, em caso afirmativo, notifique alguma dessas alterações. Então, você configuraria um hasChangesbooleano e o definiria para |= diff (a,b)então |= dif(b,c)etc. Aqui está um breve exemplo:

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
fonte
10
Sim, o mesmo vale em Java. Mas vale a pena notar que essa operação OR nãoy|=expr é um curto-circuito (ao contrário y = y || expr), o que significa que exprsempre é avaliada. Isso não foi óbvio para mim pela primeira vez :) Portanto, é importante observar antes de refatorar que a substituição y|=exprnãoy=y||x é semanticamente equivalente , caso exprrealmente tenha efeitos colaterais.
NIA
1
E, tendo isso em mente, no seu caso com hasChangesele iria provavelmente ser melhor a preferir y=y||xformulário para beneficiar a curto ciruit, porque quando você encontrou qualquer mudança não é realmente necessário para fazer diffs susequent porque você já sabe a resposta. (Especialmente importante na situação da vida real quando os objetos comparados são complicados e diffing-los eles não é muito rápido)
NIA
@NIA Obrigado pela votação. Sim, eu concordo com o seu ponto de vista sobre curto-circuito.
dbrin
2
@FranklinYu, é claro, não detalhes de implementação. O curto-circuito não é mencionado especificamente no local que você referenciou apenas porque não é a peculiaridade - é o comportamento padrão e normal para a maioria dos operadores. A peculiaridade é, na verdade, o curto-circuito de ||e &&, e nas seções correspondentes 15.23 e 15.24 da especificação, esse fato é claramente declarado, e essa diferença de |e &é enfatizada.
NIA
2
@FranklinYu Então eu acho que não havia necessidade de dizer algo sobre isso novamente na seção que você referenciou (15.26.2 "Operadores de atribuição de compund") apenas porque as atribuições de compond são simplesmente sempre sem curto-circuito (não existem operadores ||=e &&=que seriam infringir a regra e exigir menção especial).
NIA
13

É um encurtamento para isso:

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

E |é um pouco sábio OU.

Até Helge
fonte
3

Nota: || = não existe. (lógico ou) Você pode usar

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

ou

y = expr ? true : y;  // expr is always evaluated.
lãs
fonte
4
Não está completo: você ainda pode usar y |= exprcom booleanos e ele fornece o mesmo resultado yque suas variantes, com a nota importante de que não é curto-curto , o que significa que o expr sempre é avaliado, mesmo no caso dey==true
NIA