There is a difference, though it is rather minor. The key question is whether any step of the process is done by software smart enough to deduce that if x==0
, then x==2
and x==5
must be false.
At the Java bytecode level, they typically produce different results. There's no obligation that the compiler be smart enough to analyze the difference. (Eugene's answer to the related question shows that Sun's Java 12 compiler is indeed smart enough to make this optimization for you in some cases)
Just in time Compilers tend to be rather aggressive. They are more likely to realize that the code can only flow through one of the three branches and optimize it away. But that's still a tool-dependent statement. The Java language itself treats them as different.
Now, speaking practically, this will not matter in the slightest unless you are doing a very tight loop. The #1 rule in optimization is "profile, then optimize." There's no reason to optimize such details in at least 99% of cases.
To be specific, in the example you give, even if a compiler and JIT fails to optimize the code for you, the performance cost will be negligible. On an "average" CPU, a successfully predicted branch is roughly a tenth of the cost of a function call, so the fact that you called doSomething()
on these branches will dwarf the cost. If the extra calls cause some additional branch misprediction, you may see worse effects, but nothing as expensive as the fact that you called a function.
Now, assuming that doSomething()
was actually a placeholder for something fast like x += 1
, then you would need to profile to determine if it was right.
So, my recommendation would be to write if/if/if
or if/else if/else if
based on whichever one is correct. Whichever one makes the most sense for the kind of logic you want to use is the right answer. If this is intended to be a branch where exactly one path is taken, I'd recommend else if
. If this is intended to be a case where the function might execute many branches in the future, but it just so happens that the current list of branches are mutually exclusive, do if/if/if
to convey to the reader the intended results.
Then profile. Always profile. If you find this function is a hot spot, then consider worrying about whether the if statements are expensive.
As an aside, its difficult for a compiler to prove that they can convert if
into else if
. It must do an analysis of x to see whether it is possible for another thread to modify it. If it is a local variable, no other thread may modify it. However, if it is a member variable, its possible for another thread to modify x
in the middle of your if/if/if
block, causing it to take two paths. You may know that nobody else will modify x
like this, but the compiler has to prove it before making such an optimization, or at least prove that what it writes is consistent with its implementation for the rules for Java's Memory Model.