Opérateur de raccourci "or-assignment" (|=) en Java

j'ai une longue série de comparaisons à faire en Java, et j'aimerais savoir si l'un ou plusieurs d'entre eux reviennent en vrai. La chaîne de comparaisons était longue et difficile à lire, donc je l'ai décomposé pour la lisibilité, et est allé automatiquement à l'utilisation d'un opérateur de raccourci |= plutôt que negativeValue = negativeValue || boolean .

boolean negativeValue = false;
negativeValue |= (defaultStock < 0);
negativeValue |= (defaultWholesale < 0);
negativeValue |= (defaultRetail < 0);
negativeValue |= (defaultDelivery < 0);

j'attends negativeValue pour être vrai si tout de la valeur par défaut les valeurs sont négatives. Est-ce valable? Fera-t-il ce à quoi je m'attendais? Je ne pouvais pas le voir mentionné sur le site de Sun ou stackoverflow, mais Eclipse ne semble pas avoir de problème avec elle et le code compile et court.


de même, si je voulais effectuer plusieurs intersections logiques, pourrais-je utiliser &= au lieu de && ?

77
demandé sur Raedwald 2010-03-21 12:06:34

8 réponses

le |= est un opérateur d'assignation composé ( JLS 15.26.2 ) pour l'opérateur logique booléen | ( JLS 15.22.2 ); à ne pas confondre avec le conditionnel-ou || ( JLS 15.24 ). Il y a aussi &= et ^= correspondant à la version d'assignation composée des booléens logiques & et ^ respectivement.

In autrement dit, pour boolean b1, b2 , ces deux sont équivalents:

 b1 |= b2;
 b1 = b1 | b2;

la différence entre les opérateurs logiques ( & et | ) par rapport à leurs homologues conditionnels ( && et || ) est que les premiers ne font pas de "shortcircuit"; les seconds le font. C'est-à-dire:

  • & et | toujours évaluer les deux opérandes
  • && et || évaluer l'opérande de droite conditionnellement ; l'opérande de droite est évaluée uniquement si sa valeur pourrait affecter le résultat de l'opération binaire. Cela signifie que le bon opérande N'est pas évalué quand:
    • l'opérande de gauche de && évalue à false
      • (car peu importe ce que l'opérande de droite évalue, l'expression entière est false )
    • l'opérande de gauche de || évalue à true
      • (car peu importe ce que l'opérande de droite évalue, l'expression entière est true )

donc, pour revenir à votre question initiale, oui, cette construction est valide, et bien que |= ne soit pas exactement un raccourci équivalent pour = et || il n'calculer ce que vous voulez. Puisque le côté droit de l'opérateur |= dans votre usage est une simple opération de comparaison d'entier, le fait que | ne court-circuite pas est insignifiant.

il y a des cas, quand courtcircuit est désiré, ou même exigé, mais votre scénario n'est pas l'un d'eux.

il est regrettable que, contrairement à d'autres langues, Java n'ait pas &&= et ||= . C'était discuté dans la question pourquoi Java n'a-t-il pas des versions d'assignations composées des opérateurs conditionnel-et et conditionnel-ou? (&&=, ||=) .

184
répondu polygenelubricants 2017-05-23 12:34:08

ce n'est pas un opérateur de" raccourci "(ou de court-circuitage) de la façon dont | | / et && sont (en ce qu'ils ne vont pas évaluer le RHS s'ils connaissent déjà le résultat basé sur le LHS) mais il fera ce que vous voulez en termes de travail .

comme exemple de la différence, ce code sera amende si text est nul:

boolean nullOrEmpty = text == null || text.equals("")

alors que ce ne sera pas:

boolean nullOrEmpty = false;
nullOrEmpty |= text == null;
nullOrEmpty |= text.equals(""); // Throws exception if text is null

(évidemment vous pouvez faire "".equals(text) pour ce cas particulier - j'essaie juste de démontrer le principe.)

16
répondu Jon Skeet 2010-03-21 09:12:10

vous pourriez avoir juste une déclaration. Exprimé sur plusieurs lignes, il se lit presque exactement comme votre code échantillon, mais moins impératif:

boolean negativeValue
    = defaultStock < 0 
    | defaultWholesale < 0
    | defaultRetail < 0
    | defaultDelivery < 0;

pour les expressions les plus simples, utiliser | peut être plus rapide que || parce que même si cela évite de faire une comparaison, cela signifie utiliser une branche implicitement et cela peut être beaucoup plus cher.

3
répondu Peter Lawrey 2014-09-17 18:31:54

bien qu'il puisse être exagéré pour votre problème, le Guava bibliothèque a une certaine syntaxe agréable avec Predicate s et fait court-circuit évaluation de ou/et Predicate s.

essentiellement, les comparaisons sont transformées en objets, empaquetées dans une collection, puis itérées. Pour ou prédit, le premier vrai hit retourne de l'itération, et vice versa pour et.

1
répondu Carl 2010-03-22 14:28:50

S'il s'agit de lisibilité, j'ai le concept de séparation des données testées de la logique de test. Exemple de Code:

// declare data
DataType [] dataToTest = new DataType[] {
    defaultStock,
    defaultWholesale,
    defaultRetail,
    defaultDelivery
}

// define logic
boolean checkIfAnyNegative(DataType [] data) {
    boolean negativeValue = false;
    int i = 0;
    while (!negativeValue && i < data.length) {
        negativeValue = data[i++] < 0;
    }
    return negativeValue;
}

le code semble plus verbeux et explicite. Vous pouvez même créer un tableau dans l'appel de méthode, comme ceci:

checkIfAnyNegative(new DataType[] {
    defaultStock,
    defaultWholesale,
    defaultRetail,
    defaultDelivery
});

il est plus lisible que 'chaîne de comparaison', et a également l'avantage de performance de court-circuiter (au coût de l'allocation de tableau et appel de méthode).

Edit: Il est possible d'obtenir encore plus de lisibilité en utilisant simplement les paramètres varargs:

la signature de la méthode serait:

boolean checkIfAnyNegative(DataType ... data)

Et l'appel pourrait ressembler à ceci:

checkIfAnyNegative( defaultStock, defaultWholesale, defaultRetail, defaultDelivery );
1
répondu Krzysztof Jabłoński 2013-04-26 08:11:53
List<Integer> params = Arrays.asList (defaultStock, defaultWholesale, 
                                       defaultRetail, defaultDelivery);
int minParam = Collections.min (params);
negativeValue = minParam < 0;
0
répondu Roman 2010-03-21 09:21:31

/ / booléen logique ou

| bit à bit OU

| = opérateur d'inclusion et d'affectation en Bit

la raison pour laquelle |= ne shortcircit pas est parce qu'il fait un bitwise ou pas un ou logique. C'est-à-dire:


C |= 2 is same as C = C | 2

Tutorial pour les opérateurs java

0
répondu oneklc 2013-01-11 19:15:04

C'est un vieux post mais afin de fournir une perspective différente pour les débutants, je voudrais donner un exemple.

je pense que le cas d'utilisation le plus courant pour un opérateur composé similaire serait += . Je suis sûr que nous avons tous écrit quelque chose comme ceci:

int a = 10;   // a = 10
a += 5;   // a = 15

Quel était le but de ceci? Il était d'éviter d'écrire la variable a deux fois dans la même ligne. (Est-ce que je manque quelque chose de supérieur ici?)

Ainsi, la ligne suivante fait exactement la même chose, en évitant de taper la variable b1 deux fois dans la même ligne.

b1 |= b2;
0
répondu oxyt 2018-04-17 08:53:57