Java's return value in try-catch-finally mechanism
What I found in the Java language specification at least defines that your code snippet should return 3. Of course, it does not mention how the JVM should implement this, and what possible optimizations one could do.
Section 14.20.2 defines that
If execution of the try block completes abruptly for any other reason R, then the finally block is executed. Then there is a choice:
- If the finally block completes normally, then the try statement completes abruptly for reason R.
- If the finally block completes abruptly for reason S, then the try statement completes abruptly for reason S (and reason R is discarded).
And the start of chapter14 (section 14.1 to be more precise) specifies what a normal and abrupt completion is. For example a return
with a given value is an abrupt completion.
Hence in this case, the finally
block completes abruptly (reason: return
with a given value), so the try
will complete abruptly for the same reason (and return 3). This is confirmed in section 14.17 about the return statement as well
If evaluation of the Expression completes normally, producing a value V, then the return statement completes abruptly, the reason being a return with value V.
FWIW, I get a warning on function:
public static int function(){
try{
return 1;
}catch(Exception e){
return 2;
}finally{
return 3; //WARNING on this line
}
}
Ie. it tells me "finally block does not complete normally". I still get 3 as returned value no matter what.
Anyway, if I try this other example:
public class TestFinally {
public static void main(String[] args) {
int returnValue = function();
System.out.println("Return value: " + returnValue);
}
public static int function() {
try {
return 1;
}
catch (Exception e) {
return 2;
}
finally {
System.out.println("i don't know if this will get printed out.");
}
}
}
the output will be (obviously)
i don't know if this will get printed out.
Return value: 1
I have no idea how the JVM implements it, but the simplest way to look at it (at least conceptually) would be:
- the return value in the "try" is pushed onto the stack,
- then the "finally" block is executed,
- the new return value is pushed onto the stack
- the function exits, and the return value is popped from the stack, thus ignoring the first one.
Very neat question indeed.
The implementation is up to the JVM, and there are many JVMs. You could dig into OpenJDK's source code to see how it implements finally
, but this wouldn't be the only way to do it. As far as the language is concerned, the important thing is the behavior.
I don't understand point 2 -- why does finally
exist? it is not as you suggest somehow just a means to return an error code. You don't have to return from within finally
at all. The construct exists to ensure that some kind of clean-up code is run after some section of code no matter how it terminates, whether normally or via exception or return.