If the return in the try block is reached, it transfers control to the finally block, and the function eventually returns normally (not a throw).
If an exception occurs, but then the code reaches a return from the catch block, control is transferred to the finally block and the function eventually returns normally (not a throw).
In your example, you have a return in the finally, and so regardless of what happens, the function will return 34, because finally has the final (if you will) word.
Although not covered in your example, this would be true even if you didn't have the catch and if an exception were thrown in the try block and not caught. By doing a return from the finally block, you suppress the exception entirely. Consider:
public class FinallyReturn {
public static final void main(String[] args) {
System.out.println(foo(args));
}
private static int foo(String[] args) {
try {
int n = Integer.parseInt(args[0]);
return n;
}
finally {
return 42;
}
}
}
If you run that without supplying any arguments:
$ java FinallyReturn
...the code in foo throws an ArrayIndexOutOfBoundsException. But because the finally block does a return, that exception gets suppressed.
This is one reason why it's best to avoid using return in finally.
What is the purpose of `finally` in `try/catch/finally`?
java - Difference between try-finally and try-catch - Stack Overflow
language agnostic - Why use try โฆ finally without a catch clause? - Software Engineering Stack Exchange
coding style - Throwing an exception inside finally - Software Engineering Stack Exchange
Videos
If the return in the try block is reached, it transfers control to the finally block, and the function eventually returns normally (not a throw).
If an exception occurs, but then the code reaches a return from the catch block, control is transferred to the finally block and the function eventually returns normally (not a throw).
In your example, you have a return in the finally, and so regardless of what happens, the function will return 34, because finally has the final (if you will) word.
Although not covered in your example, this would be true even if you didn't have the catch and if an exception were thrown in the try block and not caught. By doing a return from the finally block, you suppress the exception entirely. Consider:
public class FinallyReturn {
public static final void main(String[] args) {
System.out.println(foo(args));
}
private static int foo(String[] args) {
try {
int n = Integer.parseInt(args[0]);
return n;
}
finally {
return 42;
}
}
}
If you run that without supplying any arguments:
$ java FinallyReturn
...the code in foo throws an ArrayIndexOutOfBoundsException. But because the finally block does a return, that exception gets suppressed.
This is one reason why it's best to avoid using return in finally.
Here is some code that show how it works.
class Test
{
public static void main(String args[])
{
System.out.println(Test.test());
}
public static String test()
{
try {
System.out.println("try");
throw new Exception();
} catch(Exception e) {
System.out.println("catch");
return "return";
} finally {
System.out.println("finally");
return "return in finally";
}
}
}
The results is:
try
catch
finally
return in finally
I have used try/catch when programming, and I've seen people use try/catch/finally.
According to my research, the `finally` part always executes, regardless of whether an exception was caught.
What is the purpose of that? Can't I just put the `finally` stuff after the `try/catch` stuff instead of making an extra block of code?
These are two different things:
- The catch block is only executed if an exception is thrown in the try block.
- The finally block is executed always after the try(-catch) block, if an exception is thrown or not.
In your example you haven't shown the third possible construct:
try {
// try to execute this statements...
}
catch( SpecificException e ) {
// if a specific exception was thrown, handle it here
}
// ... more catches for specific exceptions can come here
catch( Exception e ) {
// if a more general exception was thrown, handle it here
}
finally {
// here you can clean things up afterwards
}
And, like @codeca says in his comment, there is no way to access the exception inside the finally block, because the finally block is executed even if there is no exception.
Of course you could declare a variable that holds the exception outside of your block and assign a value inside the catch block. Afterwards you can access this variable inside your finally block.
Throwable throwable = null;
try {
// do some stuff
}
catch( Throwable e ) {
throwable = e;
}
finally {
if( throwable != null ) {
// handle it
}
}
These are not variations, they're fundamentally different things. finally is executed always, catch only when an exception occurs.
It depends on whether you can deal with the exceptions that can be raised at this point or not.
If you can handle the exceptions locally you should, and it is better to handle the error as close to where it is raised as possible.
If you can't handle them locally then just having a try / finally block is perfectly reasonable - assuming there's some code you need to execute regardless of whether the method succeeded or not. For example (from Neil's comment), opening a stream and then passing that stream to an inner method to be loaded is an excellent example of when you'd need try { } finally { }, using the finally clause to ensure that the stream is closed regardless of the success or failure of the read.
However, you will still need an exception handler somewhere in your code - unless you want your application to crash completely of course. It depends on the architecture of your application exactly where that handler is.
The finally block is used for code that must always run, whether an error condition (exception) occurred or not.
The code in the finally block is run after the try block completes and, if a caught exception occurred, after the corresponding catch block completes. It is always run, even if an uncaught exception occurred in the try or catch block.
The finally block is typically used for closing files, network connections, etc. that were opened in the try block. The reason is that the file or network connection must be closed, whether the operation using that file or network connection succeeded or whether it failed.
Care should be taken in the finally block to ensure that it does not itself throw an exception. For example, be doubly sure to check all variables for null, etc.
Basically, finally clauses are there to ensure proper release of a resource. However, if an exception is thrown inside the finally block, that guarantee goes away. Worse, if your main block of code throws an exception, the exception raised in the finally block will hide it. It will look like the error was caused by the call to close, not for the real reason.
Some people follow a nasty pattern of nested exception handlers, swallowing any exceptions thrown in the finally block.
SomeFileWriter writer = null;
try {
//init the writer
//write into the file
} finally {
if (writer!= null) {
try {
writer.close();
} catch (...) {
// swallow
}
}
}
In older versions of Java, you can "simplify" this code by wrapping resources in classes that do this "safe" clean up for you. A good friend of mine creates a list of anonymous types, each that provide the logic for cleaning up their resources. Then his code simply loops over the list and calls the dispose method within the finally block.
What Travis Parks said is true that exceptions in the finally block will consume any return values or exceptions from the try...catch blocks.
If you're using Java 7, though, the problem can be solved by using a try-with-resources block. According to the docs, as long as your resource implements java.lang.AutoCloseable (most library writers/readers do now), the try-with-resources block will close it for you. The additional benefit here is that any exception that occurs while closing it will be suppressed, allowing the original return value or exception to pass up.
From
FileWriter writer = null;
try {
writer = new FileWriter("myFile.txt");
writer.write("hello");
} catch(...) {
// return/throw new exception
} finally {
writer.close(); // an exception would consume the catch block's return/exception
}
To
try (FileWriter writer = new FileWriter("myFile.txt")) {
writer.write("hello");
} catch(...) {
// return/throw new exception, always gets returned even if writer fails to close
}
http://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html