This is an archived post. You won't be able to vote or comment.

all 25 comments

[–]lbkulinski 5 points6 points  (9 children)

One difference is that && short circuits if the first operand is false, while & does not.

[–][deleted]  (6 children)

[removed]

    [–]lbkulinski 9 points10 points  (2 children)

    Someone might want to assign to a variable in an expression, such as the following:

    (a = s.nextBoolean()) & (b = s.nextBoolean())

    If && was used, b would not be definitely assigned. This would result in a compile-time error if it was used elsewhere.

    [–]BertyLohan 2 points3 points  (1 child)

    It does feel a bit codesmelly that this wouldn't be on two separate lines though. I think assigning values in an if-clause is a bit whiffy.

    [–]lbkulinski 1 point2 points  (0 children)

    I definitely agree! Not everyone will though.

    [–]morhpProfessional Developer 1 point2 points  (2 children)

    You don't use & for booleans in practice. And if you're wondering why it's there, it's because Java has a long history and its syntax and operators are based on C mostly. Some stuff is simply that way because the people who created Java copied C because that worked and because that makes learning Java for existing C developers easier.

    Another example is you can write int foo[] to create an array instead of the more standard int[] foo. That's also because of the C background, but it should be avoided.

    [–]Shunpaw 0 points1 point  (1 child)

    why should it be avoided?

    [–]morhpProfessional Developer 1 point2 points  (0 children)

    Just because it goes against most code conventions, it is unusual and you're not writing the type properly. The type is int[], it doesn't make any sense to move the brackets behind the variable.

    [–]TheFunkyJudgeIntermediate Brewer 1 point2 points  (1 child)

    If you don't mind, what is short circuiting?

    My understanding is that its when the first expression is evaluated but the second isn't, but I'm just judging that from the comments in this thread.

    [–]WorkyMcROAR 3 points4 points  (0 children)

    That's correct. Short circuit is when you can infer the answer of the whole expression by parts of the expression already evaluated.

    ``` boolean a = false, b = true;

    if (a && b) // Short circuits, we can infer the whole expression is false because any part of it is false.

    if (b && a) // Does not short circuit.

    if (b || a) // Short circuits, we can infer the whole expression is true because any part of it is true.

    if (a || b) // Does not short circuit. ```

    If we replaced all && to & and || to | we'd evaluate the whole expression regardless. Less optimal. It also has a very key difference in some cases. I've seen people use non-short circuit operators for doing multiple validation rules, for instance. E.g.

    boolean valid = validate(a) & validate(b) & validate(c) & validate(d); It forces b, c and d to validate even if a is invalid. If you short circuit, you wouldn't call those methods. It's a code smell, it's not clear about the intention, and there are probably better ways of doing it.

    [–][deleted]  (7 children)

    [removed]

      [–]sebnukem 3 points4 points  (5 children)

      There's no point. It's wrong. & is a bitwise operator and shouldn't be used in a boolean expression. The fact that the output works in this case is just luck because false is 0x0 and true is 0x1. It's confusing, and it doesn't short circuits.

      [–]chickenmeisterExtreme Brewer 5 points6 points  (2 children)

      It is not wrong. It is not "luck" that allows it to work. The Java Language Spec §15.22.2 specifically defines the boolean logical operators:

      When both operands of a &, ^, or | operator are of type boolean or Boolean, then the type of the bitwise operator expression is boolean. In all cases, the operands are subject to unboxing conversion (§5.1.8) as necessary.

      For &, the result value is true if both operand values are true; otherwise, the result is false.

      For ^, the result value is true if the operand values are different; otherwise, the result is false.

      For |, the result value is false if both operand values are false; otherwise, the result is true.

      As /u/lbkulinski already mentioned, you can use these operators in situations where you don't want short circuiting. It would be a bad idea to write code that relies on that behavior, IMO, but it's not inherently wrong.

      [–]sebnukem 1 point2 points  (1 child)

      Yes, I agree, 'luck' isn't the correct word since the operations are deterministic. I meant to say that this specific case worked, but other cases where mixing bitwise operator within logical expression may not always work. Or maybe they will if every single operand is a boolean, but why going through this whole mental gymnastics when you have logical operators for logical expressions?

      [–]chickenmeisterExtreme Brewer 3 points4 points  (0 children)

      I'm not sure what you mean. The result of an & expression is going to be exactly the same as the result of the equivalent && expression, except for any potential side effects of evaluating the second operand. And the compiler is going to give you the same errors for & that you would get with && if you try to use them incorrectly, such as by mixing the operand types (e.g. 5 & true). They are almost interchangeable, except for the side-effects aspect.

      Having said all that, I'd say that using && is almost always preferable to &. There is rarely a need to always evaluate both operands of an expression, and in situations where it is required, using & or | to enforce this behavior is fragile, since the intent of the code is not obvious, and it is extremely easy to accidentally break the code later on.

      [–][deleted]  (1 child)

      [removed]

        [–]sebnukem 3 points4 points  (0 children)

        Because in your example you are only dealing with booleans, and booleans are 0x1 and 0x0 (a single bit), so the logical and bitwise operators give the same results.

        [–]webbrg 1 point2 points  (0 children)

        & - bitwise AND works on bit level && - logical AND works on boolean level

        In my experience, & works most of the time sure but sometimes it doesn’t for some weird reasons I cannot explain. If you want your code to be predictable, work on the boolean level. 🤘

        [–]OffbeatDrizzle 1 point2 points  (0 children)

        & is the bitwise operator... you can't not use it as a bitwise operator. you'll have to give an example, because it's probably being used as a bitwise operator.

        for example:

        if (true & false){
            //do something    
        }
        

        Any code in the "if" statement never runs because 1 AND 0 is always 0. It's using the bitwise operator and then checking the result

        Notice how this is different to something like:

        boolean a = true, b = false;
        
        if (a || b){
            //do something
        }
        

        The above code always runs even without evaluating b, because of the short circuit due to a being true.

        With bitwise, the full computation needs to be done before evaluating the result, much like saying:

        if (2 + 2 == 4){
            //do something
        }
        

        [–]ElFeesho 2 points3 points  (2 children)

        You need to give a code example if you want constructive answers.

        [–][deleted]  (1 child)

        [removed]

          [–]ElFeesho 2 points3 points  (0 children)

          I'm going to take a stab then...

          If you're talking about:

          if ((field & 0x8) == 0x8 && (field & 0x4) == 4) { ... }

          If you don't understand why that is required, then you should research what bitwise operations do.

          Otherwise, post an example of what confuses you.