How Java handles IF statements and efficiency

I'm just wondering how Java works when it comes to if . (Note: when I say “component” below, I mean the individual parts checked by the operator, for example a , b , c )

Which is more efficient in terms of calculations?

 if (a && b && c) { do stuff } 

or

 if (a) { if (b) { if (c) { do stuff } } } 

The reason I'm asking is because what matters is what Java does in the first version. Does he check every thing in the instruction or checks a , and if it is false , then cancel the check of the rest of the instruction?

If so, then it makes sense to put a component that is likely to fail as the first component in the instruction.

If the entire instruction is checked every time, then it makes sense to divide the components into a bunch of different operators, as in the second example.

+6
source share
9 answers

Java guarantees short circuit && and || : The operands are evaluated from left to right, and the evaluation stops as soon as the result is determined with confidence.

From JLS :

The && operator is similar to & (§15.22.2), but evaluates its right operand only if the value of its left operand is true . It is syntactically left-associative (it groups from left to right).

Operator || similar to | (§15.22.2), but evaluates its right operand only if the value of its left operand is false. It is syntactically left-associative (it is grouped from left to right).

This means that the two code snippets in your question are exactly equivalent.

+15
source

These code fragments are completely equivalent and give exactly the same bytecode:

 0: iload_1 1: ifeq 20 //a == false (0) 4: iload_2 5: ifeq 20 //b == false (0) 8: iload_3 9: ifeq 20 //c == false (0) 12: //do stuff 20: return 

Although the explanation is different, the code generator produces the same output. In the first case, due to lazy evaluation, the following terms are not evaluated, if the previous one is false . In the second case, the execution time will not deepen if the if condition if not met.

+6
source

for (a && b && c) , conditional “short circuits”, which means that as soon as one of them fails, the rest are not evaluated.

However, if getting a , b and c not so expensive, it can be a reason for premature optimization.

If some or all are expensive, then if you do

if (getA() && getB() && getC())...

then if getA() not executed, other methods are not even called.

+5
source

I was curious how the compiler would handle both cases, so I compiled the following code using Java 1.6:

 public class IfTest { public static void main(String[] args) { IfTest iffy = new IfTest(); iffy.doit(); } private void doit() { Random rand = new Random(); boolean a = rand.nextBoolean(); boolean b = rand.nextBoolean(); boolean c = rand.nextBoolean(); if (a && b && c) { System.out.println("block 1"); } if (a) { if (b) { if (c) { System.out.println("block 2"); } } } } } 

... then decompiled it with Jad . Here is the decompiler created from the class file:

 // Decompiled by Jad v1.5.8g. Copyright 2001 Pavel Kouznetsov. // Jad home page: http://www.kpdus.com/jad.html // Decompiler options: packimports(3) // Source File Name: IfTest.java import java.util.Random; public class IfTest { public IfTest() { } public static void main(String args[]) { IfTest iffy = new IfTest(); iffy.doit(); } private void doit() { Random rand = new Random(); boolean a = rand.nextBoolean(); boolean b = rand.nextBoolean(); boolean c = rand.nextBoolean(); if(a && b && c) System.out.println("block 1"); if(a && b && c) System.out.println("block 2"); } } 

I think it doesn't matter how you write it.

+5
source

The best way to check this out is to look in the Language Language Specification .

In this case, you want section 15.23 :

At run time, the first expression of the first operand is evaluated; if the result is of type Boolean, it undergoes the unpacking of the transform (§5.1.8); if the resulting value is false, the value of the conditional expression and expression is false, and the expression of the right operand is not evaluated.

So no, in the expression a && b && c , b and c not evaluated if a evalutes to false .

Note that this is not part of the behavior of the if - it is part of the behavior of the && operator. You can see the same effect just by using an expression elsewhere:

 // Still won't evaluate b and c if a is false... boolean x = a && b && c; 

(You should be aware of the behavior associated with that part of the language when you want to familiarize yourself with the specification.)

+3
source

In the first case, if evaluates to false in the first encountered state, false (this is a short circuit). Otherwise, you cannot do something like:

 if(a != null && a.toString().equals("b")) 

not getting a NullPointerException if the second part is also evaluated.

+2
source
 if (a && b && c) { do stuff } 

This is a short circuit. && will short circuit if a evaluates to false, i.e. the rest of the check fails.

Other than that, I think there is no difference between the two approaches.

+1
source

It:

 if (condition is met) { //continute to next check if (condition is met) { //continue to next check if (condition is met) { do stuff } } } 

Does the same as: if (a && b && c) { do stuff } , but takes up more space. You really don't need to worry about performance with this particular code segment, so your first option is your best bet. You can also do

 if (a && b){ if (condition is met) { do stuff } } 
+1
source

& & and || are logical short circuit operators. This means that in your example, if a is false, then the rest of the expression will not be evaluated.

If you need short logical operators, you can use both and |.

You can see the following Java language specification statement if you need confirmation: http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#15.22.2

+1
source

Source: https://habr.com/ru/post/905117/


All Articles