When an exception is thrown in a code the normal execution flow of the method is disrupted and that may result in
opened resources never getting closed. In such scenarios you do need a clean up mechanism that’s where
finally block in Java
helps.
For Example, suppose in a method you open a file and start reading it using input stream. While reading the stream an exception is thrown and the code to close the stream is never executed. That means you have a stream that is still using resources because it was never closed.
By using finally block and keeping the code to close the stream in that finally block you can ensure that the code to close the stream is always executed.
Finally block
Finally block in Java exception handling can immediately follow the try block making it a try-finally block or you can have a full try-catch-finally block. Try block must be followed by either catch or finally of course you can have both too making it a full try-catch-finally block.
Finally block in Java always executes whether exception is thrown in try block or not. In case no exception is thrown inside the try block, finally block is executed when try block exists.
When exception is thrown in a try block if there is a catch block that matches the exception type of the thrown exception that catch block is executed first and then the finally block. In case catch block can’t handle the thrown exception finally block is still executed just before the method returns.
Finally block Java example
Let’s try to see these scenarios with example Java programs-
When catch block is there and handles the thrown exceptionpublic class ExceptionDemo { public static void main(String[] args) { ExceptionDemo ed = new ExceptionDemo(); double result = ed.division(7, 0); System.out.println("result is - " + result); } private double division(int num1, int num2){ double result; try{ result = num1/num2; }catch(ArithmeticException exp){ System.out.println("Exception occurred while dividing" + exp.getMessage()); // assigining zero to result result = 0; }finally{ System.out.println("in finally block"); } return result; } }Output
Exception occurred while dividing/ by zero in finally block result is - 0.0When catch block is there but doesn’t handle the thrown exception
public class ExceptionDemo { public static void main(String[] args) { ExceptionDemo ed = new ExceptionDemo(); double result = ed.division(7, 0); System.out.println("result is - " + result); } private double division(int num1, int num2){ double result; try{ result = num1/num2; }catch(NullPointerException exp){ System.out.println("Exception occurred while dividing" + exp.getMessage()); // assigining zero to result result = 0; }finally{ System.out.println("in finally block"); } return result; } }
In catch block Exception type is changed to NullPointerException where as exception thrown is ArithmeticException. Finally block is still executed and then the exception is propagated to be handled by default handler in this case.
Outputin finally block Exception in thread "main" java.lang.ArithmeticException: / by zero at com.knpcode.ExceptionDemo.division(ExceptionDemo.java:14) at com.knpcode.ExceptionDemo.main(ExceptionDemo.java:7)
What happens if the exception is thrown in the finally block
If code enclosed in try block throws an exception and the finally block also throws an exception then exception thrown by finally clause masks the exception thrown in try block.
Let’s see an example to clarify it. Suppose you have a code to read a file and the file that is passed doesn’t exist at the given path. In that case FileNotFoundException will be thrown from the try block. You also have a finally block where you have a code to close the BufferedReader object but that is null in this case so finally block is also going to throw NullPointerException.
import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStreamReader; public class FinallyDemo { public static void main(String[] args){ BufferedReader br = null; try { br = new BufferedReader(new InputStreamReader( new FileInputStream( new File("D:\\test1.txt")))); //br = null; } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally{ System.out.println("In finally block"); try { br.close(); } catch (NullPointerException e) { // TODO Auto-generated catch block e.printStackTrace(); }catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }Output
java.io.FileNotFoundException: D:\test1.txt (The system cannot find the file specified) at java.io.FileInputStream.open0(Native Method) at java.io.FileInputStream.open(Unknown Source) at java.io.FileInputStream.(Unknown Source) at com.knpcode.FinallyDemo.main(FinallyDemo.java:16) In finally block java.lang.NullPointerException at com.knpcode.FinallyDemo.main(FinallyDemo.java:25)
That’s why you should avoid throwing exception in the finally clause. In the above code you can have an if condition checking for null to avoid NullPointerException at least.
if(br != null){ try { br.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } }
Java finally block with return
Even if there is a return statement in try block and no exception is thrown in try block, finally block will still be executed before the method returns.
public class FinallyDemo { public static void main(String[] args) { FinallyDemo fd = new FinallyDemo(); double result = fd.division(8, 4); System.out.println("result is - " + result); } private double division(int num1, int num2){ double result; try{ System.out.println("In try block"); return num1/num2; }finally{ System.out.println("in finally block"); } } }Output
In try block in finally block result is – 2.0
If you have a return statement in finally clause also then the value returned by try statement is replaced by the value returned by the finally block. Moreover it will also suppress any exception thrown from the try block. That is why there should not be any return statement in finally block. Use the finally block for what it is intended to do clean up code.
Return in finally block exampleIf we take the example code as used above and place a return statement in finally block then that value will be returned. Also note that there is an attempt to divide by zero but that exception is suppressed.
public class FinallyDemo { public static void main(String[] args) { FinallyDemo fd = new FinallyDemo(); double result = fd.division(8, 0); System.out.println("result is - " + result); } private double division(int num1, int num2){ double result; try{ System.out.println("In try block"); return num1/num2; }finally{ System.out.println("in finally block"); return 6; } } }Output
In try block in finally block result is – 6.0
If you comment the return statement in finally block and then run the program you can see the exception.
Exception in thread "main" In try block in finally block java.lang.ArithmeticException: / by zero at com.knpcode.FinallyDemo.division(FinallyDemo.java:17) at com.knpcode.FinallyDemo.main(FinallyDemo.java:9)
When is Java finally block not executed
Though finally block will always be executed whether any exception is thrown in try block or not. But, there are certain scenarios when finally block in Java is not executed.
If the JVM exits while the try or catch code is being executed (System.exit() or JVM crash), then the finally block may not execute. Likewise, if the thread executing the try or catch code is interrupted or killed, the finally block may not execute even though the application as a whole continues.
Important points
- Finally block in Java is used to clean up code. You should put the code to close opened resources (input stream ,output stream, opened DB connection) in finally block.
- Though finally block is optional but try block must immediately be followed by either catch or finally block. You can have a full try-catch-finally block too.
- Finally block is always executed whether try block exits without any exception or because of an exception.
- Only time finally block is not executed is when JVM exits or the thread executing the try or catch code is interrupted or killed.
- If finally block throws an exception that will mask the exception thrown in try block.
- If there is a return statement in finally block that is the value returned.
- Having a return statement in finally block may suppress the thrown exception so there should not be a return statement in finally block.
That's all for the topic Java Finally Block - Exception Handling. If something is missing or you have something to share about the topic please write a comment.
You may also like
- How to Create Custom Exception Class in Java
- ClassNotFoundException in Java
- throw Vs throws in Java Exception Handling
- Java Exception Handling Best Practices
- Java String matches() Method
- Java Pass by Value or Pass by Reference
- Thread Starvation in Java
- How to Sort Java HashSet
- Spring Bean Scopes
- Name Mangling in Python With Examples
No comments:
Post a Comment