4

Possible Duplicate:
Difference in & and &&

I've read several tutorials and answer regarding short circuit operations in java and I'm still not quite understanding the difference in how java handles short circuiting for a double vertical pipe vs a double ampersand. For instance ...

Why does the logical AND short circuit evaluation fail?

Citing the JSL 15.23. Conditional-And Operator &&

The conditional-and operator && is like & (§15.22.2), but evaluates its right-hand operand only if the value of its left-hand operand is true.

public static void main( String... args ) {


    int a = 1;

    int b = 2;

    // Okay. Prints
    if( a == 1 | b == 3 ) {

        System.out.println( "Comparison via |" + "\na is " + a + "\nb is " + b );

    }

    // Okay. Prints
    if( a == 1 || b == 3 ) {

        System.out.println( "Comparison via ||" + "\na is " + a + "\nb is " + b );

    }

    // Okay. Does not print
    if( a == 1 & b == 3 ) {

        System.out.println( "Comparison via &" + "\na is " + a + "\nb is " + b );

    }

    // I don't understand. Shouldn't the Short Circuit succeed since the left side of the equation equals 1?
    if( a == 1 && b == 3 ) {

        System.out.println( "Comparison via &&" + "\na is " + a + "\nb is " + b );

    }

}
Community
  • 1
  • 1
Edward J Beckett
  • 5,061
  • 1
  • 41
  • 41
  • 3
    `|` and `&` are bitwise or/and operators; they're different from `||` and `&&`, which are the logical or/and operators. – NullUserException Nov 16 '12 at 23:37
  • I know I don't get number four though ... I'm lost there :-) – Edward J Beckett Nov 16 '12 at 23:39
  • @NullUserException: Well, they're different in terms of short-circuiting - but the JLS defines one in terms of the other... see my answer. (Note that for `boolean` operands, they're still logical operators...) – Jon Skeet Nov 16 '12 at 23:41
  • @NullUserException `|` and `&` are also non-short-circuiting logical or and and operators. – Steve Kuo Nov 17 '12 at 00:12
  • For short-circuiting to work in #4 it would have to fail the a==1 test. In that case it can conclude that the result of the && is false because false&&anything is false. In test 2 short-ciruiting is occuring but that doesn't change the result. – Chaos Crafter Mar 22 '19 at 02:50

5 Answers5

12

I don't understand. Shouldn't the Short Circuit succeed since the left side of the equation equals 1?

No, absolutely not. The point of && is that the result is only true if the left and the right operands are true; the short-circuiting means that the right operand isn't evaluated if the left operand is false, because the answer is known at that point.

You should read sections 15.23 and 15.24 of the JLS for more details:

The conditional-and operator && is like & (§15.22.2), but evaluates its right-hand operand only if the value of its left-hand operand is true.

The conditional-or operator || operator is like | (§15.22.2), but evaluates its right-hand operand only if the value of its left-hand operand is false.

Community
  • 1
  • 1
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
2

When used with booleans, the bitwise operators (| and &) are similar to the logical operators (|| and &&) except that:

  • In the case of &&, if the first argument is false the second is left unevaluated, because the whole expression must then be false. For &, both arguments are evaluated regardless.

  • In the case of ||, if the first argument is true the second is left unevaluated, because the whole expression must then be true. For |, both arguments are evaluated regardless.

This is what we mean by "short-circuiting": the process of leaving the second argument unevaluated because in certain cases we can know the value of the whole expression just from the value of the first argument.


Now you ask why the following expression is false: a == 1 && b == 3. Well, short-circuiting has nothing to do with it; a = 1 and b = 2, so the statement "a is 1 and b is 2 is evidently false, since b is not 2.

arshajii
  • 127,459
  • 24
  • 238
  • 287
  • **tl;dr**: Bitwise (`|` and `&`) operators evaluate both arguments regardless; logical operators (`||` and `&&`) *can* (but don't always) short circuit. – NullUserException Nov 16 '12 at 23:42
  • @NullUserException When do they not short circuit? – arshajii Nov 17 '12 at 00:00
  • In the OP's example it didn't short circuit. – NullUserException Nov 17 '12 at 07:14
  • @NullUserException Yes of course because `a == 1` was `true` - the logical operators short-circuit whenever they *can* short circuit. – arshajii Nov 17 '12 at 13:24
  • @NullUserException I misunderstood, thinking you were implying that there were cases where the logical operators didn't short-circuit even when they could - my mistake. Anyway, glad we're on the same page finally! – arshajii Nov 18 '12 at 16:33
1

The logical operators || and && short-circuit if the result is determined after evaluating the first operand. For || that is the case if the first operand evaluates to true, for &&, if it evaluates to false.

If the first operand of || is false, it can still yield an overall result of true if the second operand is true. Similarly, if the first operand of && is true, it can still evaluate to false if the second operand is false.

In Java, the operators | and & are not only bitwise operators (when applied to integer arguments), but also non-short-circuiting logical operators that evaluate both operands regardless of the value of the first.

Daniel Fischer
  • 181,706
  • 17
  • 308
  • 431
1

Both & and && require both sides to be true, so the code is behaving as expected.

The only difference is that & executes both sides, but && executes only the first if it is false, because the right side would the be irrelevant to the final result.

The effect of this is important for code like

if (obj == null || obj.isSomthing())

would throw an NPE if you used | and obj was null.

Bohemian
  • 412,405
  • 93
  • 575
  • 722
0
if( a == 1 && b == 3 ) {
   System.out.println( "Comparison via &&" + "\na is " + a + "\nb is " + b );
}

First it checks, if a == 1 this is true, so it has to go on and check if b == 3, this is not true, so true && false is false and you don't get output.

if you had

if( b == 3 && a == 1 ) {
       System.out.println( "Comparison via &&" + "\na is " + a + "\nb is " + b );
}

it would first check if b == 3 and since that's not the case don't even bother looking at a == 1 because false && whatever is always false, not matter what whatever is.

Does that answer your question?

jlordo
  • 37,490
  • 6
  • 58
  • 83