Search code examples
javaperformanceif-statementreturnreadability

Else after return from first part of an if statement


The implementation of library's BigInteger.gcd(...) method begins with these statements:

public BigInteger gcd(BigInteger val) {
    if (val.signum == 0)
        return this.abs();
    else if (this.signum == 0)
        return val.abs();
    ...
}

What is the purpose of the else keyword in this case? Is it just a remnant of an old code that the programmer has forgotten to delete or it impacts performance in some way?

I understand that, semantically, the versions with and without else are identical in this particular case. Quite often, however, I face the choice between

<Some method signature>(...) {
    if (...) {
        <Short branch>
        return ...;
    } else {
        <Long branch>
        return ...;
    }
}

and

<Some method signature>(...) {
    if (...) {
        <Short branch>
        return ...;
    }
    <Long branch>
    return ...;
}

Which option is better in terms of performance (note that this question is Java-specific)? If performance is almost identical in both cases, which one is better in terms of readability?


Solution

  • On my machine, using java 1.8.0_172, the two versions produce identical bytecode. So this is optimized at compile-time itself. The JIT compiler would see the same input in both cases, so the runtime performance will be identical.

    Else version:

    public class MyTest {
        public static void main(String[] args) {
            if (args.length > 2) {
                    System.out.println("More than 2");
                    return;
            } else {
                    System.out.println("Hello");
            }
        }
    }
    

    No-else version:

    public class MyTest {
        public static void main(String[] args) {
            if (args.length > 2) {
                    System.out.println("More than 2");
                    return;
            }
            System.out.println("Hello");
        }
    }
    

    Then compile them with java MyTest.java, and then get the bytecode with javap -c MyTest, compare the bytecode from the two sources. They are identical. Both generate the following bytecode:

    Compiled from "MyTest.java"
    public class MyTest {
      public MyTest();
        Code:
           0: aload_0
           1: invokespecial #1                  // Method java/lang/Object."<init>":()V
           4: return
    
      public static void main(java.lang.String[]);
        Code:
           0: aload_0
           1: arraylength
           2: iconst_2
           3: if_icmple     15
           6: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
           9: ldc           #3                  // String More than 2
          11: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
          14: return
          15: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
          18: ldc           #5                  // String Hello
          20: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
          23: return
    }
    

    Now for readability, that is subjective of course. I prefer the version without the unnecessary else.