What Is Short Circuiting and How Is It Used When Programming in Java

What is short circuiting and how is it used when programming in Java?

Short-circuiting is where an expression is stopped being evaluated as soon as its outcome is determined. So for instance:

if (a == b || c == d || e == f) {
// Do something
}

If a == b is true, then c == d and e == f are never evaluated at all, because the expression's outcome has already been determined. if a == b is false, then c == d is evaluated; if it's true, then e == f is never evaluated. This may not seem to make any difference, but consider:

if (foo() || bar() || baz()) {
// Do something
}

If foo() returns true, then bar and baz are never called, because the expression's outcome has already been determined. So if bar or baz has some other effect than just returning something (a side effect), those effects never occur.

One great example of short-circuiting relates to object references:

if (a != null && a.getFoo() != 42) {
// Do something
}

a.getFoo() would normally throw a NullPointerException if a were null, but because the expression short-circuits, if a != null is false, the a.getFoo() part never happens, so we don't get an exception.

Note that not all expressions are short-circuited. The || and && operators are short-circuited, but | and & are not, nor are * or /; in fact most operators are not.

Why use short-circuit code?

For programmers, the benefit of a less verbose syntax over another more verbose syntax can be:

  • less to type, therefore higher coding efficiency
  • less to read, therefore better maintainability.

Now I'm only talking about when the less verbose syntax is not tricky or clever in any way, just the same recognized way of doing, but in fewer characters.

It's often when you see specific constructs in one language that you wish the language you use could have, but didn't even necessarily realize it before. Some examples off the top of my head:

  • anonymous inner classes in Java instead of passing a pointer to a function (way more lines of code).
  • in Ruby, the ||= operator, to evaluate an expression and assign to it if it evaluates to false or is null. Sure, you can achieve the same thing by 3 lines of code, but why?
  • and many more...

Java logical operator short-circuiting

The && and || operators "short-circuit", meaning they don't evaluate the right-hand side if it isn't necessary.

The & and | operators, when used as logical operators, always evaluate both sides.

There is only one case of short-circuiting for each operator, and they are:

  • false && ... - it is not necessary to know what the right-hand side is because the result can only be false regardless of the value there
  • true || ... - it is not necessary to know what the right-hand side is because the result can only be true regardless of the value there

Let's compare the behaviour in a simple example:

public boolean longerThan(String input, int length) {
return input != null && input.length() > length;
}

public boolean longerThan(String input, int length) {
return input != null & input.length() > length;
}

The 2nd version uses the non-short-circuiting operator & and will throw a NullPointerException if input is null, but the 1st version will return false without an exception.

Would this be an example of short circuiting?

Yes, this is a valid example of using short-circuiting correctly:

if(customerIndex < 0 || customerIndex >= 5 || customers[customerIndex] == null)

This code works only under the assumption that || stops evaluating as soon as it gets a true - otherwise, customers[customerIndex] could be reached with an invalid index, triggering an exception.

Short circuit vs non short circuit operators

One reason you might want to use the non-short-circuiting operator is if you are somehow depending on side-effects of functions. For example.

boolean isBig(String text) {
System.out.println(text);
return text.length() > 10;
}

...
if( isBig(string1) || isBig(string2) ){
...
}

If you don't care about whether the println is executed then you should use the short circuit operations as above. However, if you want both strings to be printed always (thus depending on side effects) then you need to use the non-short-circuit operator.

Practically speaking, you almost always want to use the short-circuit operators. Relying on side effects in expressions is usually bad programming practice.

One exception is in very low level or performance-sensitive code. The short-circuiting operators can be slightly slower because they cause branching in the program execution. Also using bitwise operators allows you to do 32 or 64 parallel boolean operations as a single integer operation, which is very fast.

programming with short-circuit evaluation in Java

I would refactor it and write it like this:

char[] values = {'x', 'y', 'z', 't'};
for (char c : values) {
Bar bar = peekAndGet(c);
if (bar != null) return produce(bar);
}
return null;

Note: one good reason to do it, is that the first time I read your code I thought it looked buggy until I read your question. You want to keep those "Something looks wrong" moments for things that really are wrong.

Avoiding exceptions by short circuiting

It's a common practice to use short-circuit operator to avoid exceptions. And it is obviously standard.

JLS Section 15.24 - Conditional OR operator:

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.

  • ConditionalOrExpression:
    • ConditionalAndExpression
    • ConditionalOrExpression || ConditionalAndExpression

Given your case, it would be pretty more clear if you use Conditional && operator and change your condition to:

if (i < a.length - 1 && a[i] != a[i + 1])

The intention is more clear in this code on the first look. Frankly speaking I had to go through twice over your condition to figure out what is it doing.

Again not related to concrete question, I'll modify your for loop to use maximum index one less than you are using currently, to avoid the conditional operator entirely:

for (int i = 0; i < a.length - 1; i++) {
if (a[i] != a[i + 1]) {
System.out.println("now what : " + a[i]);
list.add(i);
}
}


Some Common Examples:

Some quite common examples where you would see the use of conditional operators to avoid exceptions are:

Overriding equals() method:

public boolean equals(Object obj) {
return obj instanceof MyClass && ((MyClass)obj).num == this.num;
}

Handling null reference in some method invocation:

// Although there are better way to do this.
if (str != null && str.equals(str2)) {
// some code
}

Avoiding division by zero:

if (x != 0 && 4/x > 1) {
// some code
}

Contrary to this, all the above codes will throw exception at runtime, if you use Boolean Logical Operator, and the first expression evaluates to false.

Benefits of using short-circuit evaluation

Short-circuiting boolean expressions are exactly equivalent to some set of nested ifs, so are as efficient as that would be.

If b doesn't have side-effects, it can still be executed in parallel with a (for any value of "in parallel", including pipelining).

If b has side effects which the CPU architecture can't cancel when branch prediction fails then yes, this might require delays which wouldn't be there if both sides were always evaluated. So it's something to look at if you do ever find that short-circuiting operators are creating a performance bottleneck in your code, but not worth worrying about otherwise.

But short-circuiting is used for control flow as much as to save unnecessary work. It's common among languages I've used, for example the Perl idiom:

open($filename) or die("couldn't open file");

the shell idiom:

do_something || echo "that failed"

or the C/C++/Java/etc idiom:

if ((obj != 0) && (obj->ready)) { do_something; } // not -> in Java of course.

In all these cases you need short-circuiting, so that the RHS is only evaluated if the LHS dictates that it should be. In such cases there's no point comparing performance with alternative code that's wrong!



Related Topics



Leave a reply



Submit