¿Qué significa "| ="? (operador igual de tubería)

249

Intenté buscar usando Google Search y Stack Overflow, pero no mostró ningún resultado. He visto esto en el código de la biblioteca de código abierto:

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

¿Qué significa "| =" ( pipe equal operator)?

wtsang02
fuente
44
Me pregunto si agregar algo como pipe equal operatoresta pregunta o cualquier otra documentación sobre el tema no ayudaría a las personas a buscar.
Denys Séguret
10
@EJP, ¿están hablando de estos documentos ? Indica claramente que los documentos carecen de documentación sobre el uso de esto.
wtsang02
36
A menos que supieras que se llamaba tubería igual, es realmente difícil de buscar sin preguntarle a alguien.
ataulm
@ataulm, de hecho, pasé un tiempo buscando en Google un término vertical barque finalmente me llevó aquí.
Ruuter
1
Posible duplicado de ¿Qué hace el operador | = en Java?
poring91

Respuestas:

323

|=se lee de la misma manera que +=.

notification.defaults |= Notification.DEFAULT_SOUND;

es lo mismo que

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

donde |está el operador OR en cuanto a bits.

Todos los operadores están referenciados aquí .

Se utiliza un operador de bit a bit porque, como es frecuente, esas constantes permiten que un int lleve banderas.

Si observas esas constantes, verás que están en potencias de dos:

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

Por lo tanto, puede usar OR en bits para agregar banderas

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

entonces

myFlags |= DEFAULT_LIGHTS;

simplemente significa que agregamos una bandera.

Y simétricamente, probamos que se establezca una bandera usando &:

boolean hasVibrate = (DEFAULT_VIBRATE & myFlags) != 0;
Denys Séguret
fuente
2
Justo como j += 1;es lo mismo que j = j + 1;.
David Schwartz
1
@ARS: No puedo pensar en un contraejemplo en Java (¿tal vez si jes así volatile?), Pero aceptaré tu palabra.
David Schwartz el
66
@DavidSchwartz Vea esto
arshajii
2
boolean hasVibrate = DEFAULT_VIBRATE & myFlags;- se puede traducir de intque booleande esa manera en Java? Eso sería válido en C, pero pensé que en Java tenía que escribirse comoboolean hasVibrate = ((DEFAULT_VIBRATE & myFlags) == DEFAULT_VIBRATE);
BlueRaja - Danny Pflughoeft el
1
@DavidSchwartz Wow, esa comparación +=finalmente hizo el truco para que lo entendiera. ¡Gracias!
C4d
39

Ya tienes suficiente respuesta para tu pregunta. Pero puede ser mi respuesta ayudarlo más sobre el |=tipo de operadores binarios.

Estoy escribiendo una tabla para operadores bit a bit : Los
siguientes son 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  
----------------------------------------------------------------------------------------

tenga en cuenta que todos los operadores son operadores binarios.

También tenga en cuenta: (para los puntos a continuación, quería agregar mi respuesta)

  • >>>es un operador bit a bit en Java que se llama desplazamiento sin signo
    pero >>>=no un operador en Java. >>> = operador

  • ~son bits de complemento bit a bit 0 to 1 and 1 to 0(operador unario) pero ~=no un operador.

  • Además, se !llama operador lógico NOT, pero !=verifica si el valor de dos operandos es igual o no, si los valores no son iguales, entonces la condición se vuelve verdadera. por ej (A != B) is true. donde como A=!Bmedios si Bse trueluego Ase convierten en false(y si Bes falseentonces Aconvertido true).

nota al margen: |no se llama tubería, sino que se llama OR, la tubería es la terminología de shell transfiere un proceso al siguiente ...

Grijesh Chauhan
fuente
99
Tenía la impresión de que "pipa" era el nombre del personaje, que es de donde proviene el término shell. Pero, mirando Wikipedia, en realidad se llama una "barra vertical" y "tubería" es específica de los comandos de shell. ¡Solo quería decir gracias por agregar esa nota al margen!
Caleb Brinkman
18

Estaba buscando una respuesta sobre lo que |=hace en Groovy y, aunque las respuestas anteriores son correctas, no me ayudaron a comprender un código particular que estaba viendo.

En particular, cuando se aplica a una variable booleana "| =" lo establecerá en VERDADERO la primera vez que encuentre una expresión veraz en el lado derecho y MANTENERÁ su valor VERDADERO para todas las llamadas subsiguientes | =. Como un pestillo.

Aquí un ejemplo simplificado de esto:

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 

Salida:

false
false
true
true

Editar : ¿Por qué es útil?

Considere una situación en la que desea saber si algo ha cambiado en una variedad de objetos y, de ser así, notifique a alguno de los cambios. Entonces, configuraría un hasChangesbooleano y lo configurará en |= diff (a,b)y luego, |= dif(b,c)etc. Aquí hay un breve ejemplo:

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
fuente
10
Sí, lo mismo ocurre en Java. Pero vale la pena señalar que dicha operación OR noy|=expr es un cortocircuito (a diferencia y = y || expr), lo que significa que exprsiempre se evalúa. Esto no fue obvio para mí por primera vez :) Por lo tanto, es importante tener en cuenta antes de refactorizar que el reemplazo y|=exprnoy=y||x es semánticamente equivalente en caso de que exprrealmente tenga efectos secundarios.
NIA
1
Y, teniendo esto en cuenta, en su caso, con la hasChangesque sería probablemente sea mejor preferir y=y||xla forma de beneficiarse de corto ciruit, porque cuando se encontró ningún cambio en realidad no es necesario hacer diferenciaciones susequent porque ya sabe la respuesta. (Especialmente importante en la situación de la vida real cuando los objetos comparados son complicados y diffno son muy rápidos)
NIA
@NIA Gracias por el voto positivo. Sí, estoy de acuerdo con su punto sobre cortocircuito.
dbrin
2
@FranklinYu, por supuesto, no es un detalle de implementación. La falta de cortocircuito no se menciona específicamente en el lugar al que hizo referencia solo porque no es la peculiaridad: es el comportamiento predeterminado y normal para la mayoría de los operadores. La peculiaridad es en realidad el cortocircuito de ||y &&, y en las secciones correspondientes 15.23 y 15.24 de la especificación, este hecho se declara claramente, y esta diferencia |y &se enfatiza.
NIA
2
@FranklinYu Así que creo que no había necesidad de decir algo acerca de esto otra vez adelante en el apartado al que hizo referencia (15.26.2 "operadores de asignación del compund") sólo porque asignaciones compond son simplemente siempre no cortocircuito (no existen ||=y &&=los operadores lo cual infrinja la regla y requiera una mención especial).
NIA
13

Es un acortamiento para esto:

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

Y |es un poco sabio OR.

Hasta Helge
fuente
3

Nota: || = no existe. (lógico o) Puedes usar

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

o

y = expr ? true : y;  // expr is always evaluated.
woens
fuente
44
No del todo completo: todavía puede usarlo y |= exprcon booleanos y da el mismo resultado yque sus variantes con la nota importante de que no es un traje corto , lo que significa que expr siempre se evalúa, incluso en el caso dey==true
NIA