Jordan
Jordan

Reputation: 166

Does an else statement slow compile time/run speed? (In situations where one could be avoided)

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)?

Upvotes: 6

Views: 1010

Answers (5)

Avinash Singh
Avinash Singh

Reputation: 3777

Testing the program with javap , I hardly see a difference except a JUMP instruction 14: goto 25 in the second case.

I don't see a reason to add else if you have nothing to execute on else statement .You may want to use it however to do logging etc.

public class Test {
    public static void main(String[] s){
        if(testMethod()){
            System.out.println("in if");
        }
        System.out.println("in else");      
    }   
    static boolean testMethod(){
        return false;
    }
}

is resulting in

    public static void main(java.lang.String[]);
      Code:
       Stack=2, Locals=1, Args_size=1
       0:   invokestatic    #16; //Method testMethod:()Z
       3:   ifeq    14
       6:   getstatic       #20; //Field java/lang/System.out:Ljava/io/PrintStream;
       9:   ldc     #26; //String in if
       11:  invokevirtual   #28; //Method java/io/PrintStream.println:
                            (Ljava/lang/String;)V
       14:  getstatic       #20; //Field java/lang/System.out:Ljava/io/PrintStream;
       17:  ldc     #34; //String in else
       19:  invokevirtual   #28; 
      //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   22:  return

and

public class Test {
    public static void main(String[] s){
        if(testMethod()){
            System.out.println("in if");
        }else{
            System.out.println("in else");
        }
    }   
    static boolean testMethod(){
        return false;
    }
}

would produce ,

public static void main(java.lang.String[]);
  Code:
   Stack=2, Locals=1, Args_size=1
   0:   invokestatic    #16; //Method testMethod:()Z
   3:   ifeq    17
   6:   getstatic       #20; //Field java/lang/System.out:Ljava/io/PrintStream;
   9:   ldc     #26; //String in if
   11:  invokevirtual   #28; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   14:  goto    25
   17:  getstatic       #20; //Field java/lang/System.out:Ljava/io/PrintStream;
   20:  ldc     #34; //String in else
   22:  invokevirtual   #28; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   25:  return

Upvotes: 0

Hot Licks
Hot Licks

Reputation: 47699

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:

  1. If there is any common finish-up/clean-up logic at the bottom of the method, it will be missed. It's easy to forget, in a large method, that the logic is there, and it's fairly easy, in a large method, to edit such logic into a method that didn't previously have it. Bugs of this sort can be hard to find.
  2. Because it essentially eliminates the option of having "clean-up" logic at the bottom of the method, it can lead to a proliferation of logic in the individual if legs, creating more clutter than the standard if/then/else.
  3. It runs counter to good "structured programming" practice.

That said, there are cases where the return-from-the-middle style is a better choice:

  1. Cases where there are multiple sequential if statements, each with a simple body and each capable of ending with return.
  2. The case of a very brief method where the "fast exit" is natural and fairly evident.
  3. The case of a "fast exit" (eg, because some data item is nil) very near the top of a longer method.

Upvotes: 6

jn1kk
jn1kk

Reputation: 5102

There is no difference in execution, it will optimize to the same thing anyways, but for readability I recommend this (using one return principle):

private void ifThisDoThat(params){
    if(!dependenciesNotMet) { // would be nicer to change this to if(dependenciesNotMet)
        ////DO STUFF HERE...
    }
}

Upvotes: 0

Francisco Paulo
Francisco Paulo

Reputation: 6322

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

Upvotes: 2

user93353
user93353

Reputation: 14039

It's a style issue. It shouldn't affect the generated code. It's not an optimization.

Personally, I always use the return if it's possible because I think it makes the code more readable - you don't have to search around for the end of the else statement.

Upvotes: 1

Related Questions