简体   繁体   中英

Why should I always use || instead of | and && instead of &?

Since I started programming Java, I've noticed that everyone was using && and || instead of & and | . What is the reason for this? I've been using && and || all this time because I didn't know you can use & and | on booleans.

class A{static{
  boolean t = true;
  boolean f = false;
  System.out.println("&ff " + (f&&f) + " " + (f&f));
  System.out.println("&ft " + (f&&t) + " " + (f&t));
  System.out.println("&tf " + (t&&f) + " " + (t&f));
  System.out.println("&tt " + (t&&t) + " " + (t&t));
  System.out.println("|ff " + (f||f) + " " + (f|f));
  System.out.println("|ft " + (f||t) + " " + (f|t));
  System.out.println("|tf " + (t||f) + " " + (t|f));
  System.out.println("|tt " + (t||t) + " " + (t|t));
}}

As far as I can tell, they are the same:

$ javac A.java && java A
&ff false false
&ft false false
&tf false false
&tt true true
|ff false false
|ft true true
|tf true true
|tt true true
Exception in thread "main" java.lang.NoSuchMethodError: main

Does using || and && improve my code in any way?


As a simple test, I replaced hundreds of occurrences with the short form, and all of my unit tests still pass.

|| and && uses short circuit evaluation

From same article

Short-circuit evaluation, minimal evaluation, or McCarthy evaluation denotes the semantics of some Boolean operators in some programming languages in which the second argument is only executed or evaluated if the first argument does not suffice to determine the value of the expression

Consider you have an object and you want to check one of its property for some value if you do:

if(obj != null & obj.ID == 1)

If your object obj is null you will get a null reference exception, since you used single & , the first condition evaluate to false , but it will still continue to the next condition and raising null reference exception.

If you used && then the second condition will never get evaluated, thus no exception.

if(obj != null && obj.ID == 1)

With your code you will not see any difference, but using bitwise | or & with multiple conditions would result in no short circuiting at all.

More Explanation.


consider that you following code:

Boolean conditionA = 2 > 1; //some condition which returns true
if(conditionA | obj.SomeTimeConsumingMethod()){

}

Now in above code snippet, suppose you have an object with a method SomeTimeConsumingMethod which takes a lot of time in processing and returns true or false . If you use single | it would evaluate both the conditions, since first conditionA is true it will process obj.SomeTimeConsumingMethod as well. End result will be true for the whole if statement since | (OR) is used.

If your condition is using double || (OR Logical operator)

if(conditionA || obj.SomeTimeConsumingMethod())

Then the second condition obj.SomeTimeConsumingMethod() will not be evaluated. This is short circuiting and that just saved you from executing some time consuming method. Still the end result is true regardless of what was returned from obj.SomeTimeConsumingMethod() .

|| is logical or, where | is the bitwise operation or. Same with && and & . Use && and || if you're in an if statement, and | or & if you're doing bit operations.

As has already been pointed out, && and || do short-circuit evaluation. & and | , with boolean operands, do the same operations but evaluate both operands regardless of the value of the first operand.

There are cases where it matters which you use, such as when the left operand is a pre-condition for exception-free evaluation of the right hand operand.

In most cases, it does not matter. I use && and || in those cases for readability, because that is the commoner choice. Using & or | with boolean operands would tend to make most Java programmers have to stop and think, and ask themselves whether there is some specific reason for it. I suspect it may be so common because of the inheritance from C and C++.

While you may get the "correct" result using the bit-wise operators, understand they do NOT represent the same thing. For instance, this works

public static void main(String[] args){
    int x = 5;
    int y = 9;
    System.out.println(x&y); // prints "1"
} 

However, this won't

public static void main(String[] args){
    int x = 5;
    int y = 9;
    System.out.println(x&&y); // Compile error: java: operator && cannot 
                              //                be applied to int,int
}

The reason you don't use bit-wise operators for boolean logic is so that it's clear what the code is trying to do (as well as knowing that it actually works). Bit-wise operators are for manipulating bit values, where as boolean operators are for evaluating first-order logic statements.

While not the same, it is along the same reasoning for using .equals() vs == for comparison -- You don't want readers guessing as to what you meant to do. It may work in some instances (like comparing constant, hard-coded strings with == ), but it is poor form because what it says is that you are asking for instance equality as opposed to value equality, which is usually implied. And using bit-wise operators implies you want to do bit manipulation, not first-order logic evaluation.

Arguing that short circuit evaluation is mandatory because of performance is weak. You can make an argument that is almost as weak: that short circuit evaluation encourages extra nondeterminism and side channels. Random optimizations or random loss of nondeterminism/side channels, I'd prefer the latter.

The only remaining argument is this: If your code base relies on short circuit behaviour, eg, the trick described by Habib ( if (obj != null && obj.ID == 1) ), then it may not be a good idea to start mixing in & , because programmers might get it confused with && . ie, if you use & / | everywhere, but only use && in a few places where you rely on short circuit evaluation, someone might make an error and put only & , it may be hard to spot. In this case, if you relied on && for performance instead of something like null checking, it may be harder to spot when someone accidentally puts & alone, since there would be no stacktrace.

Does using || and && improve my code in any way?

Let me demonstrate two examples on how the conditional boolean operators may improve your code. Compare

if (a != null && a.equals("b") || z != null && z.equals("y"))
  System.out.println("correct");

with

boolean b1 = a != null, b2 = z != null;
if (b1) b1 = b1 & a.equals("b");
if (b2) b2 = b2 & z.equals("y");
if (b1 | b2) System.out.println("correct");

which is the best way I can think of relying solely on the logical boolean operators.

Second, say you have two tests to perform: simpleTest() and heavyTest() , where the latter involves making an HTTP request and parsing the response. You have

if (simpleTest() & heavyTest()) System.out.println("success");
else throw new IllegalStateException();

and want to optimize it. What would you rather do, this:

if (simpleTest()) {
  if (heavyTest()) System.out.println("success");
  else throw new IllegalStateException("operation could not be completed");
} else throw new IllegalStateException("operation could not be completed"); 

this:

boolean b = simpleTest();
if (b) b = b & heavyTest());
if (b) System.out.println("success");
else throw new IllegalStateException("operation could not be completed");

or this:

if (simpleTest() && heavyTest()) System.out.println("success");
else throw new IllegalStateException();

Why should I always use || instead of | and && instead of &?

You shouldn't always use them, but you would do yourself a favor by making them your default because in 99.9% of uses they either don't hurt or make your code much better. Reserve the logical operators for that 0.1% of cases where you truly do need their semantics.


It has been mentioned elsewhere on this page that relying on the conditional evaluation of the right operand makes for counterintuitive code. I refuse to accept such a view on intuition because, by definition, intuition is a learned skill . It is a facility bestowed to you by evolution to recognize a pattern in situations you encounter often, and to quickly (and subconciously) cut through to the correct conclusions. One of the most important aspects of learning a language is acquiring the right intuitions. The argument that a language feature is bad because it is counterintuitive to someone who looks at it for the first time cannot be taken seriously.

In Java (and C/C++ if I remember correctly) the single "|" and "&" are bit-wise operators, not logical operators, they are used for completely different things.

You use the "&&" and "||" for boolean statements

You use the "&" and "|" for bit operations, given the following are binary numbers

dont make assumption so fast. It because this wont compile:

  static boolean f(boolean a) {
    boolean x = (true|a) ? a : x;
    return x;
  }

Bro.java:6: variable x might not have been initialized
    boolean x = (true|a) ? a : x;
                           ^

and this will:

  static boolean f(boolean a) {
    boolean x = (true||a) ? a : x;
    return x;
  }

&& and || are short cut operators. For example:

A && B 

Condition B will not be evaluated if condition A is false

A || B

Condition B will not be evaluated if condition A is true

You should always use shortcut operators for multiple conditions evaluation. | or & are used for bit-wise operations.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM