Matt Clark Matt Clark - 6 months ago 40
Java Question

return in try block vs return after the block

I have a try statement in a small static method, is there a best practice as to where I should return from?

try {
mightThrow();
return true;
} catch (Exception e) {
return false;
}


or after,

try {
mightThrow();
} catch (Exception e) {
return false;
}
return true;


Functionally, these should preform identically, is there actually a bytecode difference? Performance wise, are they the exact same?

Or is one just preferred over the other? Which and why?

kba kba
Answer

I haven't heard of an actual best practice in this matter, but you often see that when methods use premature returns, the returns true case is at the bottom, e.g.

public bool canReadFile(path) {
  if (!fileExists(path))  
    return false;

  if (!fileIsReadable(file))
    return false;

  ...
  return true;
}

Because of that, I'd suggest you follow this practice for try/catch blocks. It also makes it quicker to see what the "expected" return value is.

In regards to the bytecode, then yes, there is indeed a difference. I made a quick sample program

class TryBlock {
    public static void main(String[] args) {
        a();
        b();
    }

    public static boolean a() {
        try {
            System.out.println("A");
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    public static boolean b() {
        try {
            System.out.println("B");
        } catch (Exception e) {
            return false;
        }
        return true;
    }

}

Then compiled it and inspected the bytecode

$ javac TryBlock.java; javap -c TryBlock
Compiled from "TryBlock.java"
class TryBlock {
  TryBlock();
    Code:
       0: aload_0
       // Method java/lang/Object."<init>":()V
       1: invokespecial #1                  
       4: return

  public static void main(java.lang.String[]);
    Code:
       // Method a:()Z
       0: invokestatic  #2                  
       3: pop
       // Method b:()Z
       4: invokestatic  #3                  
       7: pop
       8: return

  public static boolean a();
    Code:
       // Field java/lang/System.out:Ljava/io/PrintStream;
       0: getstatic     #4                  
       // String A
       3: ldc           #5                  
       // Method java/io/PrintStream.println:(Ljava/lang/String;)V
       5: invokevirtual #6                  
       8: iconst_1
       9: ireturn
      10: astore_0
      11: iconst_0
      12: ireturn
    Exception table:
       from    to  target type
           0     9    10   Class java/lang/Exception

  public static boolean b();
    Code:
       // Field java/lang/System.out:Ljava/io/PrintStream;
       0: getstatic     #4                  
       // String B
       3: ldc           #8                  
       // Method java/io/PrintStream.println:(Ljava/lang/String;)V
       5: invokevirtual #6                  
       8: goto          14
      11: astore_0
      12: iconst_0
      13: ireturn
      14: iconst_1
      15: ireturn
    Exception table:
       from    to  target type
           0     8    11   Class java/lang/Exception
}

So is there a performance difference? While I haven't tested, my bet is there won't be anything noticeable. On top of that, this will hardly be the bottleneck of your application.