Why do we usually use `||` not `|`, what is the di

2020-01-25 11:42发布

I'm just wondering why we usually use logical OR || between two booleans not bitwise OR |, though they are both working well.

I mean, look at the following:

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

Can we use | instead of ||? Same thing with & and &&.

28条回答
Viruses.
2楼-- · 2020-01-25 12:19

| is a bitwise operator. || is a logical operator.

One will take two bits and or them.

One will determine truth (this OR that) If this is true or that is true, then the answer is true.

Oh, and dang people answer these questions fast.

查看更多
戒情不戒烟
3楼-- · 2020-01-25 12:20

Logical || and && check the right hand side only if necessary. The | and & check both the sides everytime.

For example:

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

Rewrite it:

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

Another example:

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

Rewrite it:

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
...
查看更多
ら.Afraid
4楼-- · 2020-01-25 12:20

The other answers have done a good job of covering the functional difference between the operators, but the answers could apply to just about every single C-derived language in existence today. The question is tagged with , and so I will endeavor to answer specifically and technically for the Java language.

& and | can be either Integer Bitwise Operators, or Boolean Logical Operators. The syntax for the Bitwise and Logical Operators (§15.22) is:

AndExpression:
  EqualityExpression 
  AndExpression & EqualityExpression

ExclusiveOrExpression:
  AndExpression 
  ExclusiveOrExpression ^ AndExpression

InclusiveOrExpression:
  ExclusiveOrExpression 
  InclusiveOrExpression | ExclusiveOrExpression

The syntax for EqualityExpression is defined in §15.21, which requires RelationalExpression defined in §15.20, which in turn requires ShiftExpression and ReferenceType defined in §15.19 and §4.3, respectively. ShiftExpression requires AdditiveExpression defined in §15.18, which continues to drill down, defining the basic arithmetic, unary operators, etc. ReferenceType drills down into all the various ways to represent a type. (While ReferenceType does not include the primitive types, the definition of primitive types is ultimately required, as they may be the dimension type for an array, which is a ReferenceType.)

The Bitwise and Logical Operators have the following properties:

  • These operators have different precedence, with & having the highest precedence and | the lowest precedence.
  • Each of these operators is syntactically left-associative (each groups left-to-right).
  • Each operator is commutative if the operand expressions have no side effects.
  • Each operator is associative.
  • The bitwise and logical operators may be used to compare two operands of numeric type or two operands of type boolean. All other cases result in a compile-time error.

The distinction between whether the operator serves as a bitwise operator or a logical operator depends on whether the operands are "convertible to a primitive integral type" (§4.2) or if they are of types boolean or Boolean (§5.1.8).

If the operands are integral types, binary numeric promotion (§5.6.2) is performed on both operands, leaving them both as either longs or ints for the operation. The type of the operation will be the type of the (promoted) operands. At that point, & will be bitwise AND, ^ will be bitwise exclusive OR, and | will be bitwise inclusive OR. (§15.22.1)

If the operands are boolean or Boolean, the operands will be subject to unboxing conversion if necessary (§5.1.8), and the type of the operation will be boolean. & will result in true if both operands are true, ^ will result in true if both operands are different, and | will result in true if either operand is true. (§15.22.2)

In contrast, && is the "Conditional-And Operator" (§15.23) and || is the "Conditional-Or Operator" (§15.24). Their syntax is defined as:

ConditionalAndExpression:
  InclusiveOrExpression 
  ConditionalAndExpression && InclusiveOrExpression

ConditionalOrExpression:
  ConditionalAndExpression 
  ConditionalOrExpression || ConditionalAndExpression

&& is like &, except that it only evaluates the right operand if the left operand is true. || is like |, except that it only evaluates the right operand if the left operand is false.

Conditional-And has the following properties:

  • The conditional-and operator is syntactically left-associative (it groups left-to-right).
  • The conditional-and operator is fully associative with respect to both side effects and result value. That is, for any expressions a, b, and c, evaluation of the expression ((a) && (b)) && (c) produces the same result, with the same side effects occurring in the same order, as evaluation of the expression (a) && ((b) && (c)).
  • Each operand of the conditional-and operator must be of type boolean or Boolean, or a compile-time error occurs.
  • The type of a conditional-and expression is always boolean.
  • At run time, the left-hand operand expression is evaluated first; if the result has type Boolean, it is subjected to unboxing conversion (§5.1.8).
  • If the resulting value is false, the value of the conditional-and expression is false and the right-hand operand expression is not evaluated.
  • If the value of the left-hand operand is true, then the right-hand expression is evaluated; if the result has type Boolean, it is subjected to unboxing conversion (§5.1.8). The resulting value becomes the value of the conditional-and expression.
  • Thus, && computes the same result as & on boolean operands. It differs only in that the right-hand operand expression is evaluated conditionally rather than always.

Conditional-Or has the following properties:

  • The conditional-or operator is syntactically left-associative (it groups left-to-right).
  • The conditional-or operator is fully associative with respect to both side effects and result value. That is, for any expressions a, b, and c, evaluation of the expression ((a) || (b)) || (c) produces the same result, with the same side effects occurring in the same order, as evaluation of the expression (a) || ((b) || (c)).
  • Each operand of the conditional-or operator must be of type boolean or Boolean, or a compile-time error occurs.
  • The type of a conditional-or expression is always boolean.
  • At run time, the left-hand operand expression is evaluated first; if the result has type Boolean, it is subjected to unboxing conversion (§5.1.8).
  • If the resulting value is true, the value of the conditional-or expression is true and the right-hand operand expression is not evaluated.
  • If the value of the left-hand operand is false, then the right-hand expression is evaluated; if the result has type Boolean, it is subjected to unboxing conversion (§5.1.8). The resulting value becomes the value of the conditional-or expression.
  • Thus, || computes the same result as | on boolean or Boolean operands. It differs only in that the right-hand operand expression is evaluated conditionally rather than always.

In short, as @JohnMeagher has repeatedly pointed out in the comments, & and | are, in fact, non-short-circuiting boolean operators in the specific case of the operands being either boolean or Boolean. With good practices (ie: no secondary effects), this is a minor difference. When the operands aren't booleans or Booleans, however, the operators behave very differently: bitwise and logical operations simply don't compare well at the high level of Java programming.

查看更多
女痞
5楼-- · 2020-01-25 12:21

If you use the || and && forms, rather than the | and & forms of these operators, Java will not bother to evaluate the right-hand operand alone.

It's a matter of if you want to short-circuit the evaluation or not -- most of the time you want to.

A good way to illustrate the benefits of short-circuiting would be to consider the following example.

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

Another benefit, as Jeremy and Peter mentioned, for short-circuiting is the null reference check:

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

more info

查看更多
登录 后发表回答