Que signifie «| =»? (opérateur égal de tuyau)


249

J'ai essayé de rechercher à l'aide de la recherche Google et du débordement de pile, mais aucun résultat n'a été affiché. J'ai vu cela dans le code de la bibliothèque open source:

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

Que signifie "| =" ( pipe equal operator)?


4
Je me demande si l'ajout de quelque chose comme pipe equal operatorà cette question ou toute autre documentation sur le sujet n'aiderait pas les gens à chercher.
Denys Séguret

10
@EJP, vous parlez de ces documents . Il indique clairement que la documentation manque de documentation sur l' utilisation de cela.
wtsang02

36
Sauf si vous saviez que cela s'appelait pipe égal, il est vraiment difficile de rechercher sans demander à quelqu'un.
ataulm

@ataulm a en effet passé du temps à faire des recherches pour trouver un terme vertical barqui m'a finalement conduit ici.
ruuter

1

Réponses:


323

|=se lit de la même manière que +=.

notification.defaults |= Notification.DEFAULT_SOUND;

est le même que

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

|est l'opérateur OU bit par bit.

Tous les opérateurs sont référencés ici .

Un opérateur bit par bit est utilisé car, comme cela est fréquent, ces constantes permettent à un int de porter des drapeaux.

Si vous regardez ces constantes, vous verrez qu'elles ont deux puissances:

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

Vous pouvez donc utiliser des bits OU pour ajouter des indicateurs

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

alors

myFlags |= DEFAULT_LIGHTS;

signifie simplement que nous ajoutons un drapeau.

Et symétriquement, nous testons un drapeau est défini en utilisant &:

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

2
Tout comme j += 1;est le même que j = j + 1;.
David Schwartz

1
@ARS: Je ne peux pas penser à un contre-exemple en Java (peut-être si jc'est le cas volatile?), Mais je vais vous croire sur parole.
David Schwartz

6
@DavidSchwartz Voir ceci
arshajii

2
boolean hasVibrate = DEFAULT_VIBRATE & myFlags;- pouvez - vous traduire de intde ce booleangenre en Java? Ce serait valable en C, mais je pensais qu'en Java, cela devait être écrit commeboolean hasVibrate = ((DEFAULT_VIBRATE & myFlags) == DEFAULT_VIBRATE);
BlueRaja - Danny Pflughoeft

1
@DavidSchwartz Wow, cette comparaison avec a +=finalement fait l'affaire pour que je le comprenne. Merci!
C4d

39

Vous avez déjà obtenu une réponse suffisante à votre question. Mais peut-être que ma réponse vous aidera davantage au sujet des |=types d'opérateurs binaires.

J'écris une table pour les opérateurs au niveau du bit : Les éléments suivants
sont valides:

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

notez que tous les opérateurs sont des opérateurs binaires.

Notez également : (pour les points ci-dessous, je voulais ajouter ma réponse)

  • >>>est un opérateur au niveau du bit en Java qui est appelé décalage non signé
    mais >>>=pas un opérateur en Java. >>> = opérateur

  • ~est un complément binaire, 0 to 1 and 1 to 0(opérateur unaire) mais ~=pas un opérateur.

  • De plus, !appelé opérateur logique NON, mais !=vérifie si la valeur de deux opérandes est égale ou non, si les valeurs ne sont pas égales, la condition devient vraie. par exemple (A != B) is true. où comme A=!Bsignifie si Best truealors Adevenu false(et si Best falsealors Adevenu true).

note de côté: |ne s'appelle pas pipe, au lieu de cela s'appelle OR, pipe est la terminologie du shell transférer un processus au suivant.


9
J'avais l'impression que "pipe" était le nom du personnage, d'où vient le terme shell. Mais, en regardant Wikipédia, cela s'appelle en fait une "barre verticale" et "pipe" est spécifique aux commandes shell. Je voulais juste vous remercier d'avoir ajouté cette note latérale!
Caleb Brinkman

18

Je cherchais une réponse sur ce qui se |=passe dans Groovy et bien que les réponses ci-dessus soient exactes, elles ne m'ont pas aidé à comprendre un morceau de code particulier que je regardais.

En particulier, lorsqu'elle est appliquée à une variable booléenne, "| =" la définira sur VRAI la première fois qu'elle rencontrera une expression véridique sur le côté droit et conservera sa valeur VRAIE pour tous les appels | | suivants. Comme un verrou.

Voici un exemple simplifié de ceci:

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 

Production:

false
false
true
true

Edit : Pourquoi est-ce utile?

Considérez une situation où vous voulez savoir si quelque chose a changé sur une variété d'objets et si c'est le cas, notifiez l'une des modifications. Donc, vous configurez un hasChangesbooléen et le définissez sur |= diff (a,b), puis |= dif(b,c)etc. Voici un bref exemple:

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
Oui, c'est la même chose en Java. Mais il convient de noter qu'une telle opération OU y|=exprn'est pas un court-circuit (contrairement y = y || expr), ce qui signifie qu'elle est exprtoujours évaluée. Ce n'était pas évident pour moi pour la première fois :) Il est donc important de noter avant de refactoriser que le remplacement y|=expry=y||xn'est pas sémantiquement équivalent au cas où il expry aurait effectivement des effets secondaires.
NIA

1
Et, ayant cela à l' esprit, dans votre cas avec hasChangesce serait sans doute préférable de préférer la y=y||xforme au profit de court ciruit, parce que quand vous avez trouvé tout changement , il est pas vraiment nécessaire de faire diffs susequent parce que vous connaissez déjà la réponse. (Particulièrement important dans la situation de la vie réelle lorsque les objets comparés sont compliqués et diffles intégrer n'est pas assez rapide)
NIA

@NIA Merci pour le vote positif. Oui, je suis d'accord avec votre point de vue sur les courts-circuits.
dbrin

2
@FranklinYu bien sûr, pas le détail de la mise en œuvre. La non-court-circuitité n'est pas spécifiquement mentionnée à l'endroit que vous avez référencé simplement parce que ce n'est pas la particularité - c'est le comportement par défaut et normal pour la plupart des opérateurs. La particularité est en fait le court circutiness de ||et &&, et dans les sections correspondantes 15,23 et 15,24 de la spécification de ce fait est clairement déclarée, et cette différence |et &est soulignée.
NIA

2
@FranklinYu Je pense donc qu'il n'y avait pas besoin de dire quelque chose à ce sujet ci-dessous dans la section que vous avez référencée (15.26.2 "Opérateurs d'affectation Compund") simplement parce que les affectations Compond sont simplement toujours non court-circuitées (il n'y a pas d' opérateurs ||=et &&=qui enfreindre la règle et exiger une mention spéciale).
NIA

13

C'est un raccourcissement pour cela:

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

Et |est un peu OU.



3

Remarque: || = n'existe pas. (logique ou) Vous pouvez utiliser

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

ou

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

4
Pas tout à fait complet: vous pouvez toujours l'utiliser y |= expravec des booléens et cela donne le même résultat yque vos variantes avec la note importante qu'il n'est pas court-circuité , ce qui signifie que expr est toujours évalué, même en cas dey==true
NIA
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.