I have a program as following:
public class Main {
public static void main(String[] args)throws Exception
{
int res = test();
System.out.println("after call , res = " + res) ;
}
public static int test()throws Exception
{
try
{
return 10/0;
}
finally
{
System.out.println("finally") ;
}
}
}
after run above program , following result saw in console:
finally
Exception in thread "main" java.lang.ArithmeticException: / by zero
at Main.test(Main.java:17)
at Main.main(Main.java:7)
this behavior is normal because exception thrown to main method.
Then I change code as following :
public class Main {
public static void main(String[] args)throws Exception
{
int res = test();
System.out.println("after call , res = " + res) ;
}
public static int test()throws Exception
{
try
{
return 10/0;
}
finally
{
System.out.println("finally") ;
return 20;
}
}
}
When run above program I saw following result in console:
finally
after call , res = 20
My question related to second format. Why when return in finally block , exception not thrown to main method?
Yes, It is possible to have a try block without a catch block by using a final block. As we know, a final block will always execute even there is an exception occurred in a try block, except System. exit() it will execute always.
If any of the code in the try block can throw a checked exception, it has to appear in the throws clause of the method signature. If an unchecked exception is thrown, it's bubbled out of the method. The finally block is always executed, whether an exception is thrown or not.
If an exception is thrown prior to the try block, the finally code will not execute. The finally block always executes when the try block exits. So you can use finally without catch but you must use try.
When try and finally block both return value, method will ultimately return value returned by finally block irrespective of value returned by try block.
When your exception is thrown, it will first go through your finally
block.
If your finally
block does not return or throw anything then the original exception is passed on.
If your finally
block on the other hand returns a value, then the exception is no longer propagated at all.
Look at the execution of try catch finally.
From java language specification -jls-14.20.2
If the run-time type of V is not assignment compatible with a catchable exception class of any catch clause of the try statement, then the finally block is executed. Then there is a choice:
If the finally block completes normally, then the try statement completes abruptly because of a throw of the value V.
If the finally block completes abruptly for reason S, then the try statement completes abruptly for reason S (and the throw of value V is discarded and forgotten).
From the JLS (emphasis mine):
If execution of the try block completes abruptly because of a throw of a value V, then there is a choice:
[...]
If the run-time type of V is not assignment compatible with a catchable exception class of any catch clause of the try statement, then the finally block is executed. Then there is a choice:
If the finally block completes normally, then the try statement completes abruptly because of a throw of the value V.
If the finally block completes abruptly for reason S, then the try statement completes abruptly for reason S (and the throw of value V is discarded and forgotten).
This means if you return
within the finally
block, the method returns without throwing an exception.
Besides return
, there are other statementes that can cause the finally
block to complete abruptly and forget about the exception. They are defined in the JLS Section 14.1. Basically, it is break
, continue
, return
or an exception (either thrown or caused by a statement/method). The complete try/catch/finally
block then completes with this reason.
There are a few more cases ín the specification of try/catch/finally
, especially if there is no exception or a matching catch clause exists. It comes down to finally
beats catch
beats try
.
return
in the finally
section, you lose exception. Method will be finished with a normal type of a return value.return
in the finally
section, in your case, method will be finished with exception.The first case:
try {
throw new Exception();
} finally {
//Exception will be lost, normal shutdown of the method
return;
}
The second case:
try {
throw new Exception();
} finally {
//Exception won't be lost, we'll get Exception in the main method
}
The third case:
try {
throw new Exception();
} finally {
throw new IOException();
// we lost Exception, IOException will be thrown
}
Note: Using the finally
section to throw exceptions or to return values is a bad practice. This section has been created, for example, for closing external resources.
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