On innumerable (well, numerable, but many) occasions, especially within a method/function of a class, I've been in a situation where I want to do a set of operations within a void-return function, but only if(condition met)
. In most cases, I can see how (assuming that the code works) an else
statement can be removed altogether by simply returning in the if
block.
Here's a specific example, in case that didn't make sense:
With an else statement (how a teacher would show it)
private void ifThisDoThat(params){
if(dependenciesNotMet) return;
else{
////DO STUFF HERE...
}
}
Without (more parsimonious)
private void ifThisDoThat(params){
if(dependenciesNotMet) return;
//Assuming the above does not execute, DO STUFF HERE...
}
I am thinking that removing the else
statement, if an optimization at all, would be classified as a micro-optimization, but still figured I would ask for my own edification.
In closing:
Are there any benefits to using a return
to remove an else
block?
Does the compiler do extra work if I use an else
statement?
Is there a reason to always use the else
(in case of errors, or for some other reason)?
It is false optimization. The compiler may actually take longer to compile, with a return from the middle, and any optimizing compiler will produce essentially the same executable code for both forms.
In terms of style, sometimes one style is good, sometimes another. The dangers of the return-immediately style are:
if
legs, creating more clutter than the standard if/then/else.That said, there are cases where the return-from-the-middle style is a better choice:
if
statements, each with a simple body and each capable of ending with return. One quick test can answer you that. Imagine that you have:
public void x(int i){
if(i == 0){
System.out.println("zero");
return;
}
System.out.println("not zero");
}
public void y(int i){
if(i == 0){
System.out.println("zero");
return;
}
else {
System.out.println("not zero");
}
}
If you take a look at the compiled code (use javap -v <class>
):
Code for x:
public void x(int);
flags: ACC_PUBLIC
Code:
stack=2, locals=2, args_size=2
0: iload_1
1: ifne 13
4: getstatic #16 // Field java/lang/System.out:Ljava/io/PrintStream;
7: ldc #22 // String zero
9: invokevirtual #24 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
12: return
13: getstatic #16 // Field java/lang/System.out:Ljava/io/PrintStream;
16: ldc #30 // String not zero
18: invokevirtual #24 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
21: return
LineNumberTable:
line 6: 0
line 7: 4
line 8: 12
line 10: 13
line 11: 21
LocalVariableTable:
Start Length Slot Name Signature
0 22 0 this Lpt/kash/Test;
0 22 1 i I
StackMapTable: number_of_entries = 1
frame_type = 13 /* same */
Code for y:
public void y(int);
flags: ACC_PUBLIC
Code:
stack=2, locals=2, args_size=2
0: iload_1
1: ifne 13
4: getstatic #16 // Field java/lang/System.out:Ljava/io/PrintStream;
7: ldc #22 // String zero
9: invokevirtual #24 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
12: return
13: getstatic #16 // Field java/lang/System.out:Ljava/io/PrintStream;
16: ldc #30 // String not zero
18: invokevirtual #24 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
21: return
LineNumberTable:
line 14: 0
line 15: 4
line 16: 12
line 19: 13
line 21: 21
LocalVariableTable:
Start Length Slot Name Signature
0 22 0 this Lpt/kash/Test;
0 22 1 i I
StackMapTable: number_of_entries = 1
frame_type = 13 /* same */
The difference is... none. The compiler is smart enough to optimize the code.
So, the bottom line is (as has been stated): Optimize for readibility and simplicity
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With