web-dev-qa-db-fra.com

Pourquoi utilisons-nous habituellement `||` pas `|`, quelle est la différence?

Je me demande simplement pourquoi nous utilisons habituellement OR || logique entre deux booléens pas au niveau des bits OR |, bien qu'ils fonctionnent bien tous les deux.

Je veux dire, regardez ce qui suit:

if(true  | true)  // pass
if(true  | false) // pass
if(false | true)  // pass
if(false | false) // no pass
if(true  || true)  // pass
if(true  || false) // pass
if(false || true)  // pass
if(false || false) // no pass

Pouvons-nous utiliser | au lieu de ||? Même chose avec & et &&.

211
Eng.Fouad

Si vous utilisez les formes || et &&, plutôt que les formes | et & de ces opérateurs, Java ne cherchera pas à évaluer le droit Opérande main seule.

C'est une question de savoir si vous voulez court-circuiter l'évaluation ou non - la plupart du temps que vous souhaitez.

Un bon moyen d'illustrer les avantages du court-circuit serait de considérer l'exemple suivant.

Boolean b = true;
if(b || foo.timeConsumingCall())
{
   //we entered without calling timeConsumingCall()
}

Comme le mentionnent Jeremy et Peter, un autre avantage en matière de court-circuit est la vérification de référence nulle:

if(string != null && string.isEmpty())
{
    //we check for string being null before calling isEmpty()
}

plus d'infos

338
Shawn

|ne fait pas évaluation de court-circuit dans les expressions booléennes. || arrêtera d'évaluer si le premier opérande est vrai, mais | ne le fera pas.

De plus, | peut être utilisé pour effectuer l'opération au niveau du bit sur les valeurs d'octet/short/int/long. || ne peut pas.

81
Michael Myers

Donc, juste pour construire sur les autres réponses avec un exemple, le court-circuitage est crucial dans les vérifications défensives suivantes:

if (foo == null || foo.isClosed()) {
    return;
}

if (bar != null && bar.isBlue()) {
    foo.doSomething();
}

Utiliser | et & à la place pourrait provoquer un NullPointerException ici.

64
Paul Bellora

Logique || et && ne vérifie le côté droit que si nécessaire. Les | et & vérifient les deux côtés à chaque fois.

Par exemple:

int i = 12;
if (i == 10 & i < 9) // It will check if i == 10 and if i < 9
...

Réécris-le:

int i = 12;
if (i == 10 && i < 9) // It will check if i == 10 and stop checking afterward because i != 10
...

Un autre exemple:

int i = 12;
if (i == 12 | i > 10) // It will check if i == 12 and it will check if i > 10
...

Réécris-le:

int i = 12;
if (i == 12 || i > 10) // It will check if i == 12, it does, so it stops checking and executes what is in the if statement
...
39
Dair

Notez également un piège commun: les opérateurs non paresseux ont priorité sur les opérateurs paresseux, donc:

boolean a, b, c;
a || b && c; //resolves to a || (b && c)
a | b && c; //resolves to (a | b) && c

Soyez prudent lorsque vous les mélangez.

17
Mister Smith

Outre le court-circuit, il convient également de garder à l’esprit que faire une opération de logique au niveau du bit sur des valeurs autres que 0 ou 1 a une signification très différente de celle de la logique conditionnelle. Bien que ce soit généralement la même chose pour | et ||, avec & et &&, vous obtenez des résultats très différents (par exemple, 2 & 4 vaut 0/faux alors que 2 && 4 vaut 1/vrai).

Si ce que vous obtenez d'une fonction est en fait un code d'erreur et que vous testez l'absence de 0, cela peut être très important.

Ce n'est pas un problème dans Java où vous devez explicitement transtyper en booléen ou le comparer à 0, mais dans d'autres langages ayant une syntaxe similaire (C/C++ et autres), il peut en être ainsi. assez déroutant.

Notez également que & et | ne peut s’appliquer qu’aux valeurs de type entier et pas à tout ce qui peut être équivalent à un test booléen. Encore une fois, dans les langages non Java, il y a pas mal de choses qui peuvent être utilisées comme booléens avec une comparaison implicite != 0 (pointeurs, flottants, objets avec operator bool(), etc.) et des opérateurs au niveau du bit sont presque toujours absurdes dans ces contextes.

15
fluffy

La seule fois où vous utiliseriez | ou & au lieu de || ou &&, c’est lorsque vous avez des expressions booléennes très simples et que le coût du raccourci (une branche) est: supérieur au temps que vous enregistrez en ne évaluant pas les expressions ultérieures.

Cependant, il s'agit d'une micro-optimisation qui importe rarement, sauf dans le code le plus bas.

9
Peter Lawrey

a | b: évalue b dans tout cas

a || b: évalue b seulement si a est évalué à faux

8
user18596

|| est la logique ou l'opérateur alors que | est le bitwise ou l'opérateur.

boolean a = true;
boolean b = false;

if (a || b) {
}

int a = 0x0001;
a = a | 0x0002;
8
Jorge Ferreira

En plus du fait que | est un opérateur de bits: || est un opérateur de court-circuit - lorsqu'un élément est faux, il ne vérifie pas les autres.

 if(something || someotherthing)
 if(something | someotherthing)

si quelque chose est VRAI, || ne sera pas évaluer quelque chose, tandis que | ça ira. Si les variables de vos instructions if sont en réalité des appels de fonction, utilisez || est peut-être économiser beaucoup de performance.

7
Michael Stum

Les opérateurs || et && sont appelés opérateurs conditionnels, tandis que | et & sont appelés opérateurs binaires. Ils servent des objectifs différents.

Les opérateurs conditionnels fonctionnent uniquement avec les expressions dont la valeur boolean est évaluée de manière statique à gauche et à droite.

Les opérateurs au niveau des bits fonctionnent avec tous les opérandes numériques.

Si vous souhaitez effectuer une comparaison logique, vous devez utiliser opérateurs conditionnels, car vous ajouterez un type de sécurité à votre code.

3
Bruno Reis
| is the binary or operator

|| is the logic or operator
3
Lucas S.

1). (Expression1 | expression2), | L'opérateur évaluera expression2, que le résultat de expression1 soit vrai ou faux.

Exemple:

class Or 
{
    public static void main(String[] args) 
    {
        boolean b=true;

        if (b | test());
    }

    static boolean test()
    {
        System.out.println("No short circuit!");
        return false;
    }
}

2). (Expression1 || expression2), || L'opérateur n'évaluera pas expression2 si expression1 est vraie.

Exemple:

class Or 
{
    public static void main(String[] args) 
    {
        boolean b=true;

        if (b || test())
        {
            System.out.println("short circuit!");
        }
    }

    static boolean test()
    {
        System.out.println("No short circuit!");
        return false;
    }
}
2
Veeresh

Une note de côté: Java a | = mais pas un || =

Un exemple de quand vous devez utiliser || est quand la première expression est un test pour voir si la deuxième expression exploserait. par exemple. Utiliser un seul | dans les cas suivants, il pourrait en résulter un NPE.

public static boolean isNotSet(String text) {
   return text == null || text.length() == 0;
}
2
Peter Lawrey

Les autres réponses ont permis de couvrir la différence fonctionnelle entre les opérateurs, mais elles pourraient s’appliquer à peu près à tous les langages dérivés de C qui existent à ce jour. La question porte la mention Java , et je vais donc tenter de répondre de manière spécifique et technique au langage Java.

& et | peuvent être des opérateurs entiers au niveau du bit, ou des opérateurs logiques booléens. La syntaxe des opérateurs binaires et logiques ( §15.22 ) est la suivante:

AndExpression:
  EqualityExpression 
  AndExpression & EqualityExpression

ExclusiveOrExpression:
  AndExpression 
  ExclusiveOrExpression ^ AndExpression

InclusiveOrExpression:
  ExclusiveOrExpression 
  InclusiveOrExpression | ExclusiveOrExpression

La syntaxe de EqualityExpression est définie dans §15.21 , ce qui nécessite RelationalExpression définie dans §15.2 , qui à son tour nécessite ShiftExpression et ReferenceType défini dans §15.19 et §4. , respectivement. ShiftExpression nécessite AdditiveExpression défini dans §15.18 , qui continue à explorer en profondeur, définissant les opérations arithmétiques de base, unaires, etc. _ ReferenceType approfondit tous les façons de représenter un type. (Bien que ReferenceType n'inclue pas les types primitifs, la définition des types primitifs est finalement requise, car ils peuvent être le type de dimension d'un tableau qui est a ReferenceType.)

Les opérateurs binaires et logiques ont les propriétés suivantes:

  • Ces opérateurs ont une priorité différente, avec & ayant la priorité la plus élevée et | la priorité la plus basse.
  • Chacun de ces opérateurs est syntaxiquement gauche-associatif (chacun des groupes de gauche à droite).
  • Chaque opérateur est commutatif si les expressions d'opérande n'ont pas d'effets secondaires.
  • Chaque opérateur est associatif.
  • Les opérateurs au niveau des bits et logiques peuvent être utilisés pour comparer deux opérandes de type numérique ou deux opérandes de type boolean. Tous les autres cas entraînent une erreur lors de la compilation.

La distinction selon que l'opérateur joue le rôle d'opérateur au niveau du bit ou d'opérateur logique dépend du fait que les opérandes sont "convertibles en un type intégral primitif" ( §4.2 ) ou qu'ils soient de type boolean ou Boolean ( §5.1.8 ).

Si les opérandes sont des types intégraux, une promotion numérique binaire ( §5.6.2 ) est effectuée sur les deux opérandes, les laissant tous les deux sous la forme longs ou ints pour l'opération. Le type de l'opération sera le type des opérandes (promus). À ce stade, & sera bitwise AND, ^ sera bitwise OU, et | sera bitwise inclus OU. ( §15.22.1 )

Si les opérandes sont boolean ou Boolean, ils seront sujets à une conversion unboxing si nécessaire ( §5.1.8 ) et le type de l'opération sera boolean. & donnera true si les deux opérandes sont true, ^ donnera true si les deux opérandes sont différents et | dans true si l'un des opérandes est true. ( §15.22.2 )

En revanche, && est le "Conditional-And Operator" ( §15.2 ) et || est l'opérateur "conditionnel-or" ( §15.24 ). Leur syntaxe est définie comme suit:

ConditionalAndExpression:
  InclusiveOrExpression 
  ConditionalAndExpression && InclusiveOrExpression

ConditionalOrExpression:
  ConditionalAndExpression 
  ConditionalOrExpression || ConditionalAndExpression

&& ressemble à &, sauf qu'il n'évalue que l'opérande droit si l'opérande gauche est true. || ressemble à |, sauf qu'il n'évalue que l'opérande droit si l'opérande gauche est false.

Conditionnel-And a les propriétés suivantes:

  • L'opérateur conditionnel-et est syntaxiquement gauche-associatif (il groupe de gauche à droite).
  • L'opérateur conditionnel et est totalement associatif à la fois aux effets secondaires et à la valeur du résultat. Autrement dit, pour toutes les expressions a, b et c, l'évaluation de l'expression ((a) && (b)) && (c) produit le même résultat, les mêmes effets indésirables se produisant dans le même ordre, comme évaluation de l'expression (a) && ((b) && (c)).
  • Chaque opérande de l'opérateur conditionnel et doit être de type boolean ou Boolean, sinon une erreur de compilation se produit.
  • Le type d'une expression conditionnelle et expression est toujours boolean.
  • Au moment de l'exécution, l'expression de l'opérande de gauche est évaluée en premier; si le résultat est de type Boolean, il est soumis à une conversion unboxing ( §5.1.8 ).
  • Si la valeur résultante est false, la valeur de l'expression conditionnelle-and est false et l'expression de l'opérande de droite n'est pas évaluée.
  • Si la valeur de l'opérande de gauche est true, l'expression de droite est évaluée. si le résultat est de type Boolean, il est soumis à une conversion unboxing ( §5.1.8 ). La valeur résultante devient la valeur de l'expression conditionnelle.
  • Ainsi, && calcule le même résultat que & sur les opérandes boolean. Il ne diffère que par le fait que l'expression de l'opérande de droite est évaluée conditionnellement plutôt que toujours.

Conditionnel-Or a les propriétés suivantes:

  • L'opérateur conditionnel-ou est syntaxiquement gauche-associatif (il groupe de gauche à droite).
  • L'opérateur conditionnel-ou est totalement associatif à la fois aux effets secondaires et à la valeur du résultat. Autrement dit, pour toutes les expressions a, b et c, l'évaluation de l'expression ((a) || (b)) || (c) produit le même résultat, les mêmes effets indésirables se produisant dans le même ordre, comme évaluation de l'expression (a) || ((b) || (c)).
  • Chaque opérande de l'opérateur conditionnel-ou doit être de type boolean ou Boolean, sinon une erreur de compilation se produit.
  • Le type d'une expression conditionnelle ou expression est toujours boolean.
  • Au moment de l'exécution, l'expression de l'opérande de gauche est évaluée en premier; si le résultat est de type Boolean, il est soumis à une conversion unboxing ( §5.1.8 ).
  • Si la valeur résultante est true, la valeur de l'expression conditionnelle ou expression est true et l'expression de l'opérande de droite n'est pas évaluée.
  • Si la valeur de l'opérande de gauche est false, l'expression de droite est évaluée. si le résultat est de type Boolean, il est soumis à une conversion unboxing ( §5.1.8 ). La valeur résultante devient la valeur de l'expression conditionnelle.
  • Ainsi, || calcule le même résultat que | sur boolean ou Boolean opérandes. Il ne diffère que par le fait que l'expression de l'opérande de droite est évaluée conditionnellement plutôt que toujours.

En bref, comme l'a souligné à plusieurs reprises @JohnMeagher dans les commentaires, & et | sont en fait des opérateurs booléens ne court-circuitant pas dans le cas spécifique où les opérandes sont soit boolean ou Boolean. Avec les bonnes pratiques (c'est-à-dire: pas d'effets secondaires), il s'agit d'une différence mineure. Lorsque les opérandes ne sont pas booleans ou Booleans, cependant, les opérateurs se comportent très différemment: les opérations au niveau du bit et logiques ne ne vous comparez pas bien au niveau élevé de la programmation Java.

2
Brian S

Une différence principale est que || et && présentent un "court-circuit", de sorte que le RHS ne sera évalué que si nécessaire.

Par exemple.

if (a || b) {
    path1...
} else {
    path2..
}

Si a est vrai, alors b ne sera pas testé et chemin1 sera exécuté. Si | a été utilisé, alors les deux côtés seraient évalués même si "a" est vrai.

Voir ici et ici , pour un peu plus d'informations.

J'espère que cela t'aides.

1
Alex H

Lorsque j'ai eu cette question, j'ai créé un code de test pour avoir une idée à ce sujet.

public class HelloWorld{

   public static boolean bool(){
      System.out.println("Bool");
      return true;
   }

   public static void main(String []args){

     boolean a = true;
     boolean b = false;

     if(a||bool())
     {
        System.out.println("If condition executed"); 
     }
     else{
         System.out.println("Else condition executed");
     }

 }
}

Dans ce cas, nous ne changeons que la valeur du côté gauche de si la condition ajoute a ou b.

|| Scénario, lorsqu'il est à gauche vrai [if (a || bool ())]

sortie "If condition executed"

|| Scénario, lorsqu'il est à gauche faux [if (b || bool ())]

Sortie-

Bool
If condition executed

Conclusion of ||Lorsque vous utilisez ||, le côté droit ne vérifie que lorsque le côté gauche est faux.

| Scénario, lorsqu'il est à gauche vrai [if (a | bool ())]

Sortie-

Bool
If condition executed

| Scénario, côté gauche faux [if (b | bool ())]

Sortie-

Bool
If condition executed

Conclusion of |Lorsque vous utilisez |, vérifiez les côtés gauche et droit.

1
Dev4World

La différence fondamentale entre eux est que | convertit d'abord les valeurs en binaire, puis exécute le bit ou l'opération. Pendant ce temps, || ne convertit pas les données en binaire et exécute simplement l'expression ou sur son état d'origine.

int two = -2; int four = -4;
result = two | four; // bitwise OR example

System.out.println(Integer.toBinaryString(two));
System.out.println(Integer.toBinaryString(four));
System.out.println(Integer.toBinaryString(result));

Output:
11111111111111111111111111111110
11111111111111111111111111111100
11111111111111111111111111111110

En savoir plus: http://javarevisited.blogspot.com/2015/01/difference-between-bitwsie-and-logical.html#ixzz45PCxdQhk

1
Avinash Nath

|| retourne une valeur booléenne en OU deux valeurs (c'est pourquoi on l'appelle LOGICAL ou)

C'EST À DIRE:

if (A || B) 

Renverrait vrai si A ou B est vrai, ou faux si les deux sont faux.

| est un opérateur qui effectue une opération au niveau du bit sur deux valeurs. Pour mieux comprendre les opérations au niveau des bits, vous pouvez lire ici:

http://en.wikipedia.org/wiki/Bitwise_operation

1
FlySwat

Le non-court-circuitage peut être utile. Parfois, vous voulez vous assurer que deux expressions sont évaluées. Par exemple, supposons que votre méthode supprime un objet de deux listes distinctes. Vous voudrez peut-être faire quelque chose comme ça:

class foo {

    ArrayList<Bar> list1 = new ArrayList<Bar>();
    ArrayList<Bar> list2 = new ArrayList<Bar>();

    //Returns true if bar is removed from both lists, otherwise false.
    boolean removeBar(Bar bar) {
        return (list1.remove(bar) & list2.remove(bar));
    }
}

Si votre méthode utilisait plutôt l'opérande conditionnel, il ne pourrait pas supprimer l'objet de la deuxième liste si la première liste renvoyait la valeur false.

//Fails to execute the second remove if the first returns false.
boolean removeBar(Bar bar) {
    return (list1.remove(bar) && list2.remove(bar));
}

Ce n'est pas incroyablement utile, et (comme avec la plupart des tâches de programmation), vous pouvez le réaliser avec d'autres moyens. Mais c'est un cas d'utilisation d'opérandes au niveau des bits.

1
ktbiz

Il existe de nombreux cas d'utilisation suggérant pourquoi vous devriez utiliser || plutôt que |. Certains cas d'utilisation doivent obligatoirement utiliser l'opérateur | pour vérifier toutes les conditions.

Par exemple, si vous souhaitez vérifier la validation du formulaire et que vous souhaitez afficher l'utilisateur tous les champs non valides avec des textes d'erreur plutôt que le premier seul champ non valide.

|| opérateur serait,

   if(checkIfEmpty(nameField) || checkIfEmpty(phoneField) || checkIfEmpty(emailField)) {
      // invalid form with one or more empty fields
   }

   private boolean checkIfEmpty(Widget field) {
      if(field.isEmpty()) {
        field.setErrorMessage("Should not be empty!");
        return true;
      }
      return false;
   }

Donc, avec l'extrait ci-dessus, si l'utilisateur soumet le formulaire avec TOUS les champs vides, SEULEMENT nameField sera affiché avec un message d'erreur. Mais si vous le changez en,

   if(checkIfEmpty(nameField) | checkIfEmpty(phoneField) | checkIfEmpty(emailField)) {
      // invalid form with one or more empty fields
   }

Le message d'erreur approprié sera affiché sur chaque champ, quelles que soient les conditions true.

0
Bharath Mg

d'habitude j'utilise quand il y a pré incrément et post incrément. Regardez le code suivant:

package ocjpPractice;
/**
 * @author tithik
 *
 */
public class Ex1 {

    public static void main(String[] args) {
    int i=10;
    int j=9;
    int x=10;
    int y=9;
    if(i==10 | ++i>j){
        System.out.println("it will print in first if");  
        System.out.println("i is: "+i);
    }

    if(x==10 ||++x>y){
        System.out.println("it will print in second if");   
        System.out.println("x is: "+x);
    }
    }
}

sortie:

il sera imprimé en premier si
i est: 11

il sera imprimé en seconde si
x est: 10

les deux blocs if sont identiques mais le résultat est différent. quand il y a |, les deux conditions seront évaluées. Mais s'il s'agit de ||, la deuxième condition ne sera pas évaluée car la première condition est déjà vraie.

0
Tithi

| = bitwise ou, || = logique ou

0
MagicKat