Reputation: 2062
I do have the following statement:
isEnabled = false;
if(foo(arg) && isEnabled) {
....
}
public boolean foo(arg) {
some really long running code
}
Does it make sense to swap the statements inside the if?
if(isEnabled && foo(arg)) { ... }
Or does the compiler the optimization for me?
Upvotes: 4
Views: 1105
Reputation: 140427
First of all, the Java compiler (which turns java source into bytecode) is pretty dumb. Out of the many optimization techniques known to compiler constructors, just a handful (like constant folding) are implemented by javac.
Whereas the Java just-in-time compiler does many many more things; but even the JIT will not change the order of arguments for you (as that can change the semantics of the underlying program).
Finally, when thinking about this code, performance should not be the motivation behind you changing it. Instead, you should worry about the semantics too. Do you want that foo() is executed (for side effects); or maybe do you not want that foo() runs all the time?
Of course, "foo()" could be doing many many things; and not executing it might gain some performance. But most likely: it will not matter (from a performance perspective).
In other words: stay away from micro-optimisations, see here for backing reasons to that recommendation.
Upvotes: 1
Reputation: 88707
Since the compiler would have to keep the logic as it is (which includes the order of statements) it won't optimize that.
Suppose foo()
has a side effect which some other part of the code relies on, changing the order might break that. Of course this isn't good style in most cases but the compiler can't rely on or enforce style so it has to trust the developer here.
Example:
int x = 0;
boolean foo(int arg) {
x = arg;
return x > 0;
}
void someMethod(int arg) {
boolean isEnabled = false;
if(foo(arg) && isEnabled) {
//whatever
}
//here you use x, I'll simply print it
System.out.println("x=" + x);
}
void someOtherMethod(int arg) {
boolean isEnabled = false;
if(isEnabled && foo(arg)) {
//whatever
}
//here you use x, I'll simply print it
System.out.println("x=" + x);
}
Now calling the methods:
someOtherMethod(7); //foo(7) will not be called so x will still be 0
someMethod(5);
you'll get the output
x=0
x=5
Upvotes: 1
Reputation: 178421
Note that the two expressions don't have the same behavior if foo()
also has side effects.
If it is manipulating the state of the program, it makes a lot of difference if you always invoke it, or if you invoke it only as a dependency of the value of isEnabled
.
For example, consider:
boolean foo(Object arg) {
someLocalVariable = arg;
//do some calculation and return an answer
}
It matters if you always invoke foo()
, or if you invoke it only in the case where isEnabled
is turned on, resulting in the following two expressions to be completely different from each other:
if (isEnabled && foo(arg)) { ...} //local variable changes only if isEnabled==true
if (foo(arg) && isEnabled) { ...} //local variable always changes
Upvotes: 12
Reputation:
Does it make sense to swap the statements inside the if?
Yes. &&
will only evalute the sub-expressions until one is false
. Then the complete exprission will be false
, no matter what the other expressions evaluate to.
Upvotes: 2
Reputation: 7042
The compiler will not do any optimization in this case.
if(isEnabled && foo(arg)) { ... }
Is always the better approach.
Because i guess you know that when isEnabled
is false it will not evaluate foo(arg)
. And compiler will maintain your sequence of instruction.
Upvotes: 4