L'opérateur Java & = applique-t-il & ou &&?

139

En supposant

boolean a = false;

Je me demandais si je faisais:

a &= b; 

est équivalent à

a = a && b; //logical AND, a is false hence b is not evaluated.

ou d'autre part cela signifie

a = a & b; //Bitwise AND. Both a and b are evaluated.
Pakore
la source

Réponses:

146

À partir de la spécification du langage Java - 15.26.2 Opérateurs d'affectation de composés .

Une expression d'affectation composée du formulaire E1 op= E2équivaut à E1 = (T)((E1) op (E2)), où Test le type de E1, sauf que cela E1n'est évalué qu'une seule fois.

Donc a &= b;équivaut à a = a & b;.

(Dans certaines utilisations, la conversion de type fait une différence dans le résultat, mais dans celle-ci bdoit l'être booleanet la conversion de type ne fait rien.)

Et, pour mémoire, a &&= b;n'est pas Java valide. Il n'y a pas d' &&=opérateur.


En pratique, il y a peu de différence sémantique entre a = a & b;et a = a && b;. (Si best une variable ou une constante, le résultat sera le même pour les deux versions. Il y a seulement une différence sémantique quand best une sous-expression qui a des effets secondaires. Dans le &cas, l'effet secondaire se produit toujours. Dans le &&cas cela se produit en fonction de la valeur de a.)

Du côté des performances, le compromis se situe entre le coût d’évaluation bet le coût d’un test et d’une branche de la valeur de a, et l’économie potentielle en évitant une affectation inutile à a. L'analyse n'est pas simple, mais à moins que le coût de calcul ne bsoit non négligeable, la différence de performances entre les deux versions est trop faible pour être considérée.

Stephen C
la source
Votre paragraphe «en pratique» est trompeur. La seule raison d'utiliser & over && est de calculer une sous-expression non triviale dans "b"
AlexP
Clarifié. (En fait, la trivialité n'y entre pas vraiment.)
Stephen C
51

voir 15.22.2 du JLS . Pour les opérandes booléens, l' &opérateur est booléen et non au niveau du bit. La seule différence entre &&et &pour les opérandes booléens est que pour &&elle est court-circuitée (ce qui signifie que le deuxième opérande n'est pas évalué si le premier opérande est évalué à faux).

Donc , dans votre cas, si best une primitive, a = a && b, a = a & bet a &= btout faire la même chose.

Ragoût
la source
2
Donc (a & = b;) ne court-circuitera pas si b est un appel de méthode? y a-t-il quelque chose comme un opérateur "&& ="?
est le
2
Il semble que cela ne répond pas à la question; l'OP était déjà au courant des courts-circuits.
OR Mapper
21

C'est le dernier:

a = a & b;
Philippe Leybaert
la source
0

Voici un moyen simple de le tester:

public class OperatorTest {     
    public static void main(String[] args) {
        boolean a = false;
        a &= b();
    }

    private static boolean b() {
        System.out.println("b() was called");
        return true;
    }
}

La sortie est b() was calleddonc l'opérande de droite est évalué.

Donc, comme déjà mentionné par d'autres, a &= best le même que a = a & b.

user7291698
la source
-2

Je suis tombé sur une situation similaire en utilisant des booléens où je voulais éviter d'appeler b () si a était déjà faux.

Cela a fonctionné pour moi:

a &= a && b()
Daniel Testa
la source
25
Afin d'éviter les redondances (permettant toujours les courts-circuits), vous pouvez simplement écrire a=a&&b().
Unai Vivi