Andres
Andres

Reputation: 161

& vs && -- how can the first case be used?

(a > b) & (c < d), the components are evaluated left to right, so (a > b) is evaluated first. If (a > b) is false, the entire expression is false regardless of the result of the component (r < d). Nevertheless, the component (c < d) will still be evaluated. However, in the expression (a > b) && (c < d), the component (c < d) will not be evaluated if (a > b) evaluates to false. This is known as short circuiting.

Came across this paragraph in a Java book. I have been programming in various languages before, but I've never found a need for '&'. Why would one want to evaluate the second statement if it's known that the end result is not affected by it? Is there any use for it; does it come due to historical reasons?

Same question applies to | and || as well.

Upvotes: 2

Views: 571

Answers (8)

user166390
user166390

Reputation:

if(0 != ((a > b) ? 1 : 0) & ((c < d) ? 1 : 0)) {
   // but really... (a > b) && (c < d), assuming no side-effects
}

...just use the logical operators (&& and ||) for conditions ;-) That is what they were designed for. If non-shortcircuit behavior is required, then restructure the code accordingly.

I think I have seen one case that had a somewhat valid use of & in this context, but I do not recall what it was so I mustn't have found it that valid ;-) In languages like C/C++ where there is no discreet "boolean" type, the (input) and result of & can be treated such that 0 -> false and non-0 -> true. As can be seen, however, Java has to jump through some fun to get bool -> int -> bool.

The only justification for a bit-wise operator is, well, bit-wise operations, IMOHO. Bit-wise operators are most useful when performing some sort of encoding including "bit fields" and "bit masks". They are also useful when dealing with fun arising from Java's signed-only bytes, etc.

I think the bigger (only?) point to take away is that && and || are short-circuiting -- they are actually the only operators with this behavior (arguments over ?: excluded); the rest is just to explain the eager-behavior of bit-wise operators. This just goes to re-enforce the rule: do not cause side-effects in conditionals (outside of a few well-accepted idioms, but even then, keep it simple).

Happy coding.


Examples of bit-wise usage:

Imagine the use of flags which are stored into a single "integer" slot in a serialized format:

int flags = 0;
if (this.encypted) {
   flags |= EncryptedMode;
}
out.write(flags);

// later on
int flags = in.readInt();
this.encrypted = (flags & EncryptedMode) != 0;

Reading the "unsigned value" of a byte:

byte[] data = {-42, ...}; // read in from file or something
int unsignedByte = data[0] & 0xFF;

Upvotes: 1

TacticalCoder
TacticalCoder

Reputation: 6325

The difference between '&' and '&&' is not well-known and that example from the book doesn't help much.

Here's another example to show how short-circuiting work (using horrible methods having side-effects, but that's not the point).

Imagine you have this:

private int cnt;

private boolean a() {
    cnt++;
    return false;
}

private boolean b() {
    cnt++;
    return false;
}

If you execute the following:

    cnt = 0;
    if ( a() && b() ) {}
    System.out.println( cnt );

It shall print 1.

While if you execute the following:

    cnt = 0;
    if ( a() & b() ) {}
    System.out.println( cnt );

It shall print 2. Because in the latter case b() must be evaluated as per the language specs while in the first case b() must not be evaluated, as per the language specs.

Upvotes: 1

Marcelo Cantos
Marcelo Cantos

Reputation: 185862

The use of a non-short-circuit operator may speed up performance-critical code by avoiding branch mis-prediction stalls, which could easily amount to a dozen or more clock cycles.

Upvotes: 0

Nick Rolando
Nick Rolando

Reputation: 26177

Perhaps the 2nd evaluation is in the form of an assignment statement or method call, in which case you might want it to execute. I wouldn't use bitwise operators in place of logical operators like this tho. If you need something to execute passed &&, then do it prior to your logical statement and store the result in a variable.

Upvotes: 1

ratchet freak
ratchet freak

Reputation: 48196

if you expect your code to be under attack from timing attacks you want the least amount of branches (conditional execution paths) possible, this is one way to eliminate them

Upvotes: 2

Stephen C
Stephen C

Reputation: 718866

You can use & in situations where you have to evaluate both subexpressions. For example, if they both have side effects that are observable by the rest of your application.

Upvotes: 1

Andy Thomas
Andy Thomas

Reputation: 86411

The && operator is defined by the Java Language Specification to perform short-circuit evaluation.

However, the & operator is not, even when applied to boolean arguments.

You could exploit this if one of the arguments had side-effects that you did not want short-circuited. However, in my experience this is uncommon, and you'd face the risk of someone "fixing" it. It would be better separated into steps. For example, instead of:

if ( foo() & bar() ) {... }

you could say:

boolean isFoo = foo();
boolean isBar = bar();
if ( isFoo && isBar ) { ... }

Upvotes: 2

Hayden Schiff
Hayden Schiff

Reputation: 3330

Your book is confusing things. For the most part, you will only use '&&' and '||'. The single ones, '&' and '|', are bitwise operators - you can read more about them here: http://download.oracle.com/javase/tutorial/java/nutsandbolts/op3.html

Upvotes: 0

Related Questions