Java Tutorial 72 of 143
Basics
- Introduction
- Download and Install Java
- Download and Install IntelliJ IDEA, Eclipse
- Creating First Java Application in IntelliJ IDEA
- JDK vs JRE vs JVM
- Print output
- Taking Input
- Identifiers
- Keywords
- Variables
- Data Types
- Literals
- Wrapper Classes
- Operators
- Decision Making
- Loops and Jump Statements
- Project: Number Guessing Game
Methods
- Introduction
- Static Methods vs Instance Methods
- Access Modifiers
- Command Line Arguments
- Variable Arguments (Varargs)
Arrays
- Introduction
- One Dimensional Arrays
- Multidimensional Arrays
- Array Class
- Arrays Class
Strings
- Introduction
- String
- StringBuffer
- StringBuilder
- String Class Methods
- StringJoiner
- StringTokenizer
OOP & Interface
- Introduction
- Java Constructors
- Java Encapsulation
- Inheritance
- Java Polymorphism
- Java Abstraction
- Interfaces
- this Keyword
- super Keyword
- static Keyword
- final Keyword
- Access Modifiers
- Nested Classes
- Anonymous Inner Class
Collections
- Collection class
- Collection Interface
- List Interface
- ArrayList
- LinkedList
- Set Interface
- HashSet
- LinkedHashSet
- TreeSet
- Queue Interface
- PriorityQueue
- Deque
- ArrayDeque
- Map Interface in Java
- HashMap
- LinkedHashMap
- TreeMap
- Hashtable
- Iterator
- Comparable and Comparator
Exception Handling
- Introduction
- Java Exception Handling
- Java Try-Catch
- Java Finally Block
- Java throw and throws
- Java Custom Exceptions
- Java Checked vs Unchecked Exceptions
Multithreading & Concurrency
- Introduction
- Thread Class
- Runnable Interface
- Thread Life Cycle
- Thread Priority
- Synchronization
- Inter-Thread Communication
- Executor Framework
- Callable and Future
- Concurrent Collections
Java 8 Features
- Lambda Expressions
- Functional Interfaces
- Method References
- Stream API
- Optional Class
- Default and Static Methods in Interface
- Date and Time API
Advanced Java Concepts
- File Handling
- Serialization and Deserialization
- Reflection API
- Annotations
- Garbage Collection
- Memory Management
- JVM Architecture
- Class Loading
- Networking
- Regular Expressions
JDBC
- Introduction
- JDBC Driver
- JDBC Connection
- Types of Statements in JDBC
- Transactions
- ResultSet
- Metadata
- Connection Pooling
Web & Enterprise
- Servlets
- JSP
- Spring Framework
- Spring Boot
- Hibernate
- REST API Development
Practice Projects
- Project: Number Guessing Game
- Project: Banking System
- Project: Student Management System
- Project: Library Management System
- Project: Quiz Application
Quiz and Coding Practice
- Java Topic-wise Quiz
- Coding Practice Problems
- Java Basics Coding Practice Problems
- Java Exercises
Interview Questions
- Core Java Interview Questions and Answers
- Advanced Java Interview Questions and Answers
- Java Interview Questions
DSA & Competitive Programming
- Arrays and Strings
- Linked List
- Stack
- Queue
- Tree
- Graph
- Heap
- Hashing
- Sorting
- Searching
- Dynamic Programming
- Roadmap for DSA in Java
Java Finally Block
Learn how the Java finally block works, when it executes, how it works with try-catch, resource cleanup, return statements, and try-with-resources.
On this page
- What Is the Finally Block?
- Syntax of Finally
- Finally Without Catch
- Finally with Try-Catch
- When No Exception Occurs
- When an Exception Occurs
- Finally for Resource Cleanup
- Finally vs Try-With-Resources
- Finally and Return Statements
- Return from Finally
- Finally Can Override an Exception
- Finally and Exceptions in Catch
- Finally with Nested Try-Catch
- Finally and System.exit()
- When Does Finally Not Execute?
- Finally Execution Flow
- Case 1: No Exception
- Case 2: Exception Handled
- Case 3: Exception Not Handled
- Case 4: Return in Try
- Finally with Loops
- Finally and continue
- Common Uses of Finally
- Common Mistakes
- Returning from Finally
- Throwing a New Exception Without Considering the Original
- Using Finally When Try-With-Resources Is Better
- Finally vs Catch
- Finally vs Try-With-Resources
- Key Points to Remember
- Conclusion
Java Finally Block
The finally block in Java is used to execute code after a try or try-catch statement finishes. It is commonly used for cleanup operations such as closing resources.
A finally block can be used with try and catch:
try {
// Code that may throw an exception
}
catch (Exception e) {
// Handle exception
}
finally {
// Cleanup code
}
For example:
try {
int result = 10 / 2;
System.out.println(result);
}
catch (ArithmeticException e) {
System.out.println("Arithmetic error");
}
finally {
System.out.println("Finally block executed");
}
Output:
5
Finally block executed
What Is the Finally Block?
The finally block contains code that is intended to execute after the try and catch processing.
It is commonly used for operations that should happen regardless of whether an exception occurs.
Example:
try {
System.out.println("Try block");
}
finally {
System.out.println("Finally block");
}
Output:
Try block
Finally block
Unlike catch, a finally block is not used to handle an exception. Its primary purpose is cleanup or other code that should normally execute after the operation.
Syntax of Finally
The basic syntax is:
try {
// Code
}
finally {
// Code that should normally execute afterward
}
A finally block can also be used with catch:
try {
// Code
}
catch (Exception e) {
// Handle exception
}
finally {
// Cleanup
}
Finally Without Catch
A finally block does not always require a catch block.
Example:
try {
int result = 10 / 2;
System.out.println(result);
}
finally {
System.out.println("Cleanup code");
}
Output:
5
Cleanup code
If an exception occurs and there is no catch, the exception propagates after the finally block executes.
Example:
try {
int result = 10 / 0;
}
finally {
System.out.println("Finally executed");
}
Output includes:
Finally executed
followed by the uncaught ArithmeticException.
Finally with Try-Catch
The most common form combines all three blocks:
try {
// Risky code
}
catch (Exception e) {
// Exception handling
}
finally {
// Cleanup
}
Example:
try {
int result = 10 / 0;
}
catch (ArithmeticException e) {
System.out.println("Cannot divide by zero");
}
finally {
System.out.println("Execution completed");
}
Output:
Cannot divide by zero
Execution completed
The catch block handles the exception, and the finally block then executes.
When No Exception Occurs
If the try block completes successfully, the catch block is skipped and the finally block executes.
Example:
try {
int result = 10 / 2;
System.out.println(result);
}
catch (ArithmeticException e) {
System.out.println("Arithmetic error");
}
finally {
System.out.println("Finally executed");
}
Output:
5
Finally executed
Execution flow:
try
↓
No exception
↓
Skip catch
↓
finally
When an Exception Occurs
If an exception occurs inside the try block:
- Java stops executing the remaining statements in the
tryblock. - Java searches for a matching
catch. - The matching
catchexecutes if found. - The
finallyblock executes. - Execution continues after the entire statement, or the exception propagates if it remains unhandled.
Example:
try {
System.out.println("Before exception");
int result = 10 / 0;
System.out.println("After exception");
}
catch (ArithmeticException e) {
System.out.println("Exception handled");
}
finally {
System.out.println("Finally executed");
}
Output:
Before exception
Exception handled
Finally executed
The "After exception" statement is never executed.
Finally for Resource Cleanup
One traditional use of finally is closing resources.
For example:
FileReader reader = null;
try {
reader = new FileReader("data.txt");
// Read the file
}
catch (IOException e) {
System.out.println("File operation failed");
}
finally {
if (reader != null) {
try {
reader.close();
}
catch (IOException e) {
System.out.println("Unable to close file");
}
}
}
The finally block provides an opportunity to close the resource even when an exception occurs.
However, for resources that implement AutoCloseable, modern Java code should generally prefer try-with-resources.
Finally vs Try-With-Resources
Try-with-resources automatically closes resources after the try block finishes.
Instead of:
FileReader reader = null;
try {
reader = new FileReader("data.txt");
}
catch (IOException e) {
System.out.println("File error");
}
finally {
if (reader != null) {
try {
reader.close();
}
catch (IOException e) {
System.out.println("Close failed");
}
}
}
you can use:
try (FileReader reader = new FileReader("data.txt")) {
// Use reader
}
catch (IOException e) {
System.out.println("File error");
}
Try-with-resources is generally simpler and handles resource closure automatically.
Finally and Return Statements
A finally block normally executes even when a return statement appears in the try or catch block.
Example:
static int getNumber() {
try {
return 10;
}
finally {
System.out.println("Finally executed");
}
}
Calling:
System.out.println(getNumber());
Output:
Finally executed
10
The finally block executes before the method returns.
Return from Finally
Although Java permits a return statement inside finally, it is strongly discouraged because it can override a return value or suppress an exception.
Example:
static int getNumber() {
try {
return 10;
}
finally {
return 20;
}
}
The method returns:
20
The return from finally overrides the return from try.
Because this can make program behavior difficult to understand and can hide exceptions, avoid returning from finally.
Finally Can Override an Exception
A return in finally can even suppress an exception.
Example:
static int calculate() {
try {
throw new RuntimeException("Something went wrong");
}
finally {
return 10;
}
}
The method returns 10, and the exception is suppressed.
This is one reason why returning from finally should be avoided.
Finally and Exceptions in Catch
A finally block executes after a matching catch block.
Example:
try {
int result = 10 / 0;
}
catch (ArithmeticException e) {
System.out.println("Exception handled");
}
finally {
System.out.println("Cleanup");
}
Output:
Exception handled
Cleanup
If the catch block itself throws another exception, the finally block still executes before that exception propagates.
try {
int result = 10 / 0;
}
catch (ArithmeticException e) {
System.out.println("Handling exception");
throw new RuntimeException("New exception");
}
finally {
System.out.println("Finally executed");
}
Output includes:
Handling exception
Finally executed
The new exception then propagates to the caller.
Finally with Nested Try-Catch
A nested try-catch-finally structure can have multiple finally blocks.
Example:
try {
try {
int result = 10 / 0;
}
catch (ArithmeticException e) {
System.out.println("Inner catch");
}
finally {
System.out.println("Inner finally");
}
}
catch (Exception e) {
System.out.println("Outer catch");
}
finally {
System.out.println("Outer finally");
}
Output:
Inner catch
Inner finally
Outer finally
Each finally block executes according to the flow of its associated try statement.
Finally and System.exit()
There is an important exception to the normal execution behavior of finally.
If the JVM is terminated using System.exit(), normal finally execution does not occur.
Example:
try {
System.out.println("Try block");
System.exit(0);
}
finally {
System.out.println("Finally block");
}
The JVM terminates before the finally block can execute normally.
Therefore, finally should not be treated as an absolute guarantee under every possible termination condition.
When Does Finally Not Execute?
In normal Java execution, finally executes after the associated try/catch processing.
However, there are exceptional situations where it may not execute, such as:
System.exit()terminates the JVM.- The JVM terminates abnormally.
- The process is forcibly terminated.
- The operating system or runtime environment stops execution.
Therefore, saying that finally always executes is not strictly correct.
A more accurate statement is that finally normally executes when control leaves the associated try/catch statement.
Finally Execution Flow
Case 1: No Exception
try
↓
No exception
↓
finally
↓
Continue
Case 2: Exception Handled
try
↓
Exception
↓
catch
↓
finally
↓
Continue
Case 3: Exception Not Handled
try
↓
Exception
↓
No matching catch
↓
finally
↓
Exception propagates
Case 4: Return in Try
try
↓
return
↓
finally
↓
Method returns
The finally block runs before the method actually returns.
Finally with Loops
A finally block also executes when control leaves a try statement because of a break or continue.
Example:
for (int i = 0; i < 3; i++) {
try {
if (i == 1) {
break;
}
System.out.println(i);
}
finally {
System.out.println("Finally");
}
}
Output:
0
Finally
Finally
When break leaves the loop, the finally block associated with the current try still executes.
Finally and continue
Example:
for (int i = 0; i < 3; i++) {
try {
if (i == 1) {
continue;
}
System.out.println(i);
}
finally {
System.out.println("Finally");
}
}
Output:
0
Finally
Finally
2
Finally
The finally block executes before the continue takes effect.
Common Uses of Finally
The finally block can be useful for:
- Closing legacy resources
- Releasing locks
- Restoring temporary state
- Cleaning up temporary objects
- Performing operations that should normally happen after a
trystatement
For example:
Lock lock = getLock();
try {
lock.lock();
// Critical section
}
finally {
lock.unlock();
}
The finally block ensures that the lock-release operation is attempted when control leaves the try block.
Common Mistakes
Returning from Finally
Avoid:
try {
return 10;
}
finally {
return 20;
}
The finally return overrides the earlier return and can make the code confusing.
Throwing a New Exception Without Considering the Original
Be careful when throwing another exception from finally, because it can replace an exception that was already propagating.
For example:
try {
throw new RuntimeException("Original");
}
finally {
throw new RuntimeException("New");
}
The new exception can obscure the original failure.
Using Finally When Try-With-Resources Is Better
For AutoCloseable resources, prefer:
try (FileReader reader = new FileReader("data.txt")) {
// Use resource
}
rather than manually managing the resource with finally.
Finally vs Catch
finally |
catch |
|---|---|
| Used primarily for cleanup or post-processing | Used to handle an exception |
| Normally executes after try/catch processing | Executes only when its exception type matches |
| Does not receive an exception automatically | Receives the exception object |
Can be used without catch |
Must be associated with a try |
| Commonly used for cleanup | Commonly used for recovery or error handling |
Finally vs Try-With-Resources
| Finally | Try-With-Resources |
|---|---|
| General-purpose cleanup mechanism | Designed specifically for resource management |
| Cleanup code is written manually | Resources are closed automatically |
| Can become verbose | Usually concise |
| Useful for general cleanup | Best suited for AutoCloseable resources |
Key Points to Remember
finallyis used withtryand optionallycatch.- It normally executes when control leaves the associated
trystatement. - It can execute whether an exception occurs or not.
- It can be used without a
catchblock. - It is commonly associated with cleanup operations.
finallynormally executes before a method returns.- Avoid using
returninsidefinally. - An exception thrown from
finallycan replace an exception that was already propagating. System.exit()prevents normalfinallyexecution.- Try-with-resources is generally preferred for closing
AutoCloseableresources. finallyandcatchhave different purposes:catchhandles exceptions, whilefinallyis primarily for cleanup or post-processing.
Conclusion
The finally block in Java provides a mechanism for executing cleanup or post-processing code after a try statement. It normally runs whether the operation succeeds, an exception is handled, or an exception propagates.
Although finally remains useful for general cleanup, modern Java applications should generally use try-with-resources for managing files, streams, database resources, and other objects that implement AutoCloseable.
Avoid placing return or unnecessary exception-throwing logic inside finally, because doing so can override normal control flow and make errors harder to diagnose.
Related
-
Java Exception Handling
Learn Java exception handling with try-catch, finally, throw, throws, custom exceptions, checked and unchecked exceptions, and practical examples.
-
Java Try-Catch
Learn how to handle exceptions in Java using try-catch blocks, multiple catch blocks, exception types, nested try-catch, and practical examples.
-
Java throw and throws
Learn the difference between Java throw and throws, how to explicitly throw exceptions, declare exceptions in methods, and handle checked and unchecked exceptions.
-
Java Checked vs Unchecked Exceptions
Learn the difference between checked and unchecked exceptions in Java, including compiler checking, exception handling, examples, use cases, and best practices.