web-dev-qa-db-fra.com

Différences entre les opérateurs booléens: & vs && et | vs ||

Je connais les règles pour && et || mais que sont & et |? S'il vous plaît, expliquez-les-moi avec un exemple.

95
Sumithra

Ce sont les opérateurs AND au bit et OR au niveau du bit.

int a = 6; // 110
int b = 4; // 100

// Bitwise AND    

int c = a & b;
//   110
// & 100
// -----
//   100

// Bitwise OR

int d = a | b;
//   110
// | 100
// -----
//   110

System.out.println(c); // 4
System.out.println(d); // 6

Merci à Carlos d’avoir signalé la section appropriée de la spécification du langage Java ( 15.22.1 , 15.22.2 ) concernant les différents comportements de l’opérateur en fonction de ses entrées. 

En effet, lorsque les deux entrées sont booléennes, les opérateurs sont considérés comme des opérateurs logiques booléens et se comportent de manière similaire aux opérateurs conditionnel-et (&&) et conditionnel-ou (||), à la différence qu'ils ne court-circuitent pas est sécurisé:

if((a != null) && (a.something == 3)){
}

Ce n'est pas:

if((a != null) & (a.something == 3)){
}
117
Justin Niessner

Je pense que vous parlez de la signification logique des deux opérateurs, vous avez ici un résumé de table:

boolean a, b;

Operation     Meaning                       Note
---------     -------                       ----
   a && b     logical AND                    short-circuiting
   a || b     logical OR                     short-circuiting
   a &  b     boolean logical AND            not short-circuiting
   a |  b     boolean logical OR             not short-circuiting
   a ^  b     boolean logical exclusive OR
  !a          logical NOT

short-circuiting        (x != 0) && (1/x > 1)   SAFE
not short-circuiting    (x != 0) &  (1/x > 1)   NOT SAFE
99
Torres

Je sais qu'il y a beaucoup de réponses ici, mais elles semblent toutes un peu déroutantes. Ainsi, après quelques recherches dans le guide d’étude Java Oracle, j’ai proposé trois scénarios différents pour savoir quand utiliser && ou & . Ces trois scénarios sont logique AND , bitwise AND , et booléen ET .

ET logique: ET logique (ou ET conditionnel) utilise l'opérateur && . C'est court-circuité: si l'opérande de gauche est faux, l'opérande de droite ne sera pas évalué. 
Exemple:

int x = 0;
if (false && (1 == ++x) {
    System.out.println("Inside of if");
}
System.out.println(x); // "0"

Dans l'exemple ci-dessus, la valeur imprimée sur la console de x sera 0, car le premier opérande de l'instruction if est false, Java n'a donc pas besoin de calculer (1 == ++ x) et x ne sera donc pas calculé.

Bitwise AND: Bitwise AND utilise l'opérateur & . Il sert à effectuer une opération au niveau des bits sur la valeur. Il est beaucoup plus facile de voir ce qui se passe en regardant le fonctionnement sur des nombres binaires ex:

int a = 5;     //                    5 in binary is 0101
int b = 12;    //                   12 in binary is 1100
int c = a & b; // bitwise & preformed on a and b is 0100 which is 4

Comme vous pouvez le voir dans l'exemple, lorsque les représentations binaires des nombres 5 et 12 sont alignées, un AND au niveau du bit préformé ne produira qu'un nombre binaire où le même chiffre dans les deux nombres aura un 1. D'où 0101 & 1100 == 0100. Quel est le nombre décimal = 5.

Boolean AND: Maintenant, l'opérateur AND booléen se comporte de manière similaire et différente à la fois de l'opérateur AND au niveau du bit et de l'opérateur AND logique. J'aime penser que cela se produit un peu au dessus d'un bit ET entre deux valeurs booléennes (ou bits), par conséquent, il utilise & opérateur. Les valeurs booléennes peuvent également être le résultat d'une expression logique. 

Il renvoie une valeur true ou false, un peu comme le AND logique, mais contrairement au AND logique, il n'est pas court-circuité. La raison en est que, pour qu'il puisse préformer ce bit AND, il doit connaître la valeur des opérandes gauche et droit. Voici un ex:

int x = 0;
if (false & (1 == ++x) {
    System.out.println("Inside of if");
}
System.out.println(x); //"1"

Maintenant, lorsque cette instruction if est exécutée, l'expression (1 == ++ x) sera exécutée, même si l'opérande de gauche est false. Par conséquent, la valeur imprimée pour x sera 1 car elle a été incrémentée.

Ceci s'applique également à OR (||), au OR (|) et au booléen OR (|) .__ au niveau des bits J'espère que cela dissipe une certaine confusion.

23

Les opérateurs && et || sont court-circuités, ce qui signifie qu'ils n'évalueront pas leur expression de droite si la valeur de l'expression de gauche est suffisante pour déterminer le résultat.

7
Tassos Bassoukos

& et | fournir le même résultat que les && et || les opérateurs. La différence est qu’ils évaluent toujours les deux côtés de l’expression où as && et || arrêtez d’évaluer si la première condition est suffisante pour déterminer le résultat.

4
Brian Scott

En Java, les opérateurs uniques &, |, ^,! dépend des opérandes. Si les deux opérandes sont entiers, une opération au niveau du bit est effectuée. Si les deux sont des booléens, une opération "logique" est effectuée.

Si les deux opérandes ne correspondent pas, une erreur de compilation est générée.

Les opérateurs doubles &&, || se comportent de la même manière que leurs homologues uniques, mais les deux opérandes doivent être des expressions conditionnelles, par exemple:

if ((a <0) && (b <0)) {...} ou similaire, if ((a <0) || (b <0)) {...}

source: Java programming lang 4th ed

2
aaron p.

&&; || sont des opérateurs logiques .... court circuit

&; | sont des opérateurs logiques booléens .... Pas de court-circuit

Passer aux différences d'exécution sur les expressions. Les opérateurs au niveau des bits évaluent les deux côtés indépendamment du résultat du côté gauche. Mais dans le cas de l'évaluation d'expressions avec des opérateurs logiques, l'évaluation de l'expression de la main droite dépend de la condition de la main gauche.

Par exemple:

int i = 25;
int j = 25;
if(i++ < 0 && j++ > 0)
    System.out.println("OK");
System.out.printf("i = %d ; j = %d",i,j);

Cela affichera i = 26; j = 25, comme la première condition est fausse, la condition de la main droite est ignorée car le résultat est faux de toute façon, quelle que soit la condition du côté droit.

int i = 25;
int j = 25;
if(i++ < 0 & j++ > 0)
    System.out.println("OK");
System.out.printf("i = %d ; j = %d",i,j);

Mais, cela affichera i = 26; j = 26,

1
Nickhil

& et | sont des opérateurs au niveau du bit sur les types intégraux (par exemple int): http://download.Oracle.com/javase/tutorial/Java/nutsandbolts/op3.html

&& et || fonctionnent uniquement sur les booléens (et court-circuitez, comme d'autres réponses l'ont déjà dit).

1
Bruno

Peut-être qu'il peut être utile de savoir que les opérateurs AND au niveau du bit et OR au niveau du bit sont toujours évalués avant le AND conditionnel et le conditionnel OR utilisés dans la même expression.

if ( (1>2) && (2>1) | true) // false!
1
alexmeia

Bien que la différence fondamentale soit que & est utilisé pour les opérations au niveau des bits principalement sur long, int ou byte où il peut être utilisé pour un type de masque, les résultats peuvent différer même si vous l'utilisez au lieu de && logique.

La différence est plus perceptible dans certains scénarios:

  1. L'évaluation de certaines expressions prend du temps
  2. L'évaluation d'une expression ne peut être effectuée que si la précédente était vraie
  3. Les expressions ont un effet secondaire (intentionnel ou non)

Le premier point est assez simple, il ne cause pas de bugs, mais prend plus de temps. Si vous avez plusieurs vérifications différentes dans une instruction conditionnelle, placez ceux qui sont moins chers ou plus susceptibles d’échouer à gauche.

Pour le deuxième point, voir cet exemple:

if ((a != null) & (a.isEmpty()))

Cela échoue pour null, car l'évaluation de la deuxième expression produit un NullPointerException. L'opérateur logique && est fainéant, si l'opérande de gauche est faux, le résultat est faux, quel que soit l'opérande de droite.

Exemple pour le troisième point - Supposons que nous ayons une application qui utilise une base de données sans déclencheurs ni cascades. Avant de supprimer un objet de construction, nous devons remplacer le bâtiment d'un objet de département par un autre. Supposons également que le statut de l'opération est renvoyé sous la forme d'un booléen (true = succès). Ensuite:

if (departmentDao.update(department, newBuilding) & buildingDao.remove(building))

Ceci évalue les deux expressions et effectue ainsi la suppression du bâtiment même si la mise à jour du service a échoué pour une raison quelconque. Avec &&, cela fonctionne comme prévu et s’arrête après le premier échec.

Quant à a || b, il est équivalent à !(!a && !b), il s’arrête si a est vrai, aucune autre explication n’est nécessaire.

0
Vlasec

Si une expression impliquant l'opérateur booléen & est évaluée, les deux opérandes sont évalués. Ensuite, l'opérateur & est appliqué à l'opérande. 

Lorsqu'une expression impliquant l'opérateur && est évaluée, le premier opérande est évalué. Si le premier opérande est évalué à false, l'évaluation du deuxième opérande est ignorée.

Si le premier opérande renvoie la valeur true, le deuxième opérande est évalué. Si le deuxième opérande renvoie la valeur true, l'opérateur && est ensuite appliqué aux premier et deuxième opérandes.

Similaire pour | et ||.

0
RishiKesh Pathak