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?

1

3 Answers

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.

2

To me this is more a semantics and readability issue.

If your return true is at the end of the segment outside of the try/catch block, it means this function is supposed to return true value unless anything bad happened in between which interrupts the normal flow.

Instead if the return true is at the end of the try block, it means the function should only return true if all the attempts in the try block succeeded.

This difference in byte code is more or less neglectable; and I agree with @kba this is more a style issue. Many return statement at different places inside deeply embedded if blocks would usually be confusing; so it's a good practice to make your code less complex. I.e.

  1. Use flat blocks than deep embed where possible
  2. Carry less state to another code segment and/or an inner if, for or try block
  3. Use less state and flow controlling variable
  4. Use less statement like return or go because they are more or less a compulsory change of the logic flow.

Hope that helps.

Return is always set false for any type of exception. This may not be the case you will be expecting. May be some of the unexpected exceptions would cause a false value to be returned. So not a good standard way of returning in catch

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

James H. Sterling

James H. Sterling

Environmental Science & Climate Journalist

James Sterling reports on renewable energy developments, climate policy, ecological conservation, and green tech innovations around the globe.

Share this article
Twitter Facebook Pinterest