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?
Putting return where it makes sense improves readability and maintainability and makes your code simpler to understand. You shouldn't care as finally block will get executed if a return statement is encountered. Save this answer.
When you will try to execute the preceding program, you will get an unreachable code error. Key point: Any statement after return statement will result in compile-time error stating “Unreachable code”.
In a try-catch-finally block that has return statements, only the value from the finally block will be returned. When returning reference types, be aware of any updates being done on them in the finally block that could end up in unwanted results.
Yes you can write the return statement in a finally block and it will override the other return value. The output is always 2, as we are returning 2 from the finally block.
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.
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.
if
, for
or try
blockreturn
or go
because they are more or less a compulsory change of the logic flow.Hope that helps.
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