finally Block
The finally block in Java is used to execute important cleanup code regardless of whether an exception occurs or not. It ensures that critical resources are released, making programs safe and reliable.
This is a high-frequency interview topic, often asked with tricky edge cases.
What Is the finally Block?
- Always executes after try and catch
- Used for cleanup operations
- Executes whether exception occurs or not
- Ensures program stability
Basic Syntax
try {
// risky code
} catch (Exception e) {
// handling code
} finally {
// cleanup code
}
Why finally Is Important
- Closes resources (files, DB, network)
- Releases memory
- Restores system state
- Avoids resource leaks
- Ensures predictable execution
Basic Example
try {
int a = 10 / 2;
} catch (ArithmeticException e) {
System.out.println("Error");
} finally {
System.out.println("Finally block executed");
}
Output:
Finally block executed
Result: ✔ Executes even when no exception occurs
Execution Scenarios (Very Important)
1️⃣ No Exception Occurs
try {
int x = 10 / 2;
} catch (Exception e) {
} finally {
System.out.println("Finally");
}
✔ finally executes
2️⃣ Exception Occurs and Is Caught
try {
int x = 10 / 0;
} catch (ArithmeticException e) {
} finally {
System.out.println("Finally");
}
✔ finally executes
3️⃣ Exception Occurs and Is NOT Caught
try {
int x = 10 / 0;
} finally {
System.out.println("Finally");
}
✔ finally executes
❌ Program terminates after finally
Can finally Exist Without catch?
✔ Yes
try {
int x = 10 / 2;
} finally {
System.out.println("Cleanup");
}
❌ catch is optional
✔ finally is optional
When finally Does NOT Execute (Rare but Important)
1. System.exit() is Called
try {
System.exit(0);
} finally {
System.out.println("Finally");
}
❌ finally will NOT execute
2. JVM Crash / Power Failure
- JVM shuts down unexpectedly
- finally cannot run
return Statement and finally
Example
int test() {
try {
return 10;
} finally {
System.out.println("Finally");
}
}
✔ Output:
Finally
✔ Method returns 10 after finally
return in finally (Very Dangerous)
int test() {
try {
return 10;
} finally {
return 20;
}
}
❌ Output:
20
- ⚠️ finally overrides return value
- ⚠️ Strongly discouraged
finally vs try-with-resources
Traditional Cleanup
FileReader fr = null;
try {
fr = new FileReader("file.txt");
} finally {
if (fr != null) fr.close();
}
Modern Approach (Java 7+)
try (FileReader fr = new FileReader("file.txt")) {
// use file
}
- ✔ Automatic resource cleanup
- ✔ Cleaner and safer
Common Beginner Mistakes
- Writing business logic in finally
- Using return inside finally
- Forgetting that finally always executes
- Not handling resource cleanup properly
- Assuming finally always executes (ignoring System.exit)
Interview-Ready Answers
Short Answer
The finally block is used to execute cleanup code whether an exception occurs or not.
Detailed Answer
In Java, the finally block is executed after try and catch blocks regardless of whether an exception is thrown or handled. It is typically used for resource cleanup such as closing files or database connections. The only cases where finally does not execute are JVM termination or system exit.
Key Takeaway
finally guarantees cleanup. Use it for resource release, not for business logic. Avoid return inside finally to prevent unexpected behavior.
finally Block Examples (Interview Favorites)
1. Basic finally Execution
class Demo {
public static void main(String[] args) {
try {
int a = 10 / 0;
} catch (ArithmeticException e) {
System.out.println("Catch");
} finally {
System.out.println("Finally");
}
}
}
Output
Catch
Finally
2. finally Without Exception
class Demo {
public static void main(String[] args) {
try {
System.out.println("Try block");
} finally {
System.out.println("Finally block");
}
}
}
Output
Try block
Finally block
3. finally Without catch
class Demo {
public static void main(String[] args) {
try {
System.out.println("Only try");
} finally {
System.out.println("Only finally");
}
}
}
Output
Only try
Only finally
4. finally with Multiple catch
class Demo {
public static void main(String[] args) {
try {
String s = null;
s.length();
} catch (ArithmeticException e) {
System.out.println("Arithmetic");
} catch (NullPointerException e) {
System.out.println("Null");
} finally {
System.out.println("Finally executed");
}
}
}
Output
Null
Finally executed
5. finally Executes Even After return
class Demo {
static int test() {
try {
return 10;
} finally {
System.out.println("Finally");
}
}
public static void main(String[] args) {
System.out.println(test());
}
}
Output
Finally
10
6. finally Overrides return (Interview Favorite)
class Demo {
static int test() {
try {
return 10;
} finally {
return 20;
}
}
public static void main(String[] args) {
System.out.println(test());
}
}
Output
20
7. finally with Exception + return
class Demo {
static int test() {
try {
int a = 10 / 0;
return 1;
} catch (ArithmeticException e) {
return 2;
} finally {
return 3;
}
}
public static void main(String[] args) {
System.out.println(test());
}
}
Output
3
8. finally Executes When Exception Not Caught
class Demo {
public static void main(String[] args) {
try {
int a = 10 / 0;
} finally {
System.out.println("Finally executed");
}
}
}
Output
Finally executed
Exception in thread "main" java.lang.ArithmeticException
9. finally with Nested try-catch
class Demo {
public static void main(String[] args) {
try {
try {
int a = 10 / 0;
} catch (ArithmeticException e) {
System.out.println("Inner catch");
}
} finally {
System.out.println("Outer finally");
}
}
}
Output
Inner catch
Outer finally
10. finally and Resource Cleanup (Old Style)
import java.io.FileInputStream;
class Demo {
public static void main(String[] args) {
FileInputStream fis = null;
try {
fis = new FileInputStream("test.txt");
} catch (Exception e) {
System.out.println("Exception");
} finally {
try {
if (fis != null) fis.close();
System.out.println("Resource closed");
} catch (Exception e) {}
}
}
}
Output
Exception
Resource closed
11. finally vs try-with-resources
import java.io.*;
class Demo {
public static void main(String[] args) {
try (FileInputStream fis = new FileInputStream("test.txt")) {
System.out.println("Using resource");
} catch (Exception e) {
System.out.println("Exception");
}
}
}
Explanation
Resource auto-closed (no finally needed)
12. finally Not Executed with System.exit()
class Demo {
public static void main(String[] args) {
try {
System.exit(0);
} finally {
System.out.println("Finally");
}
}
}
Explanation
JVM terminates immediately
finally not executed
13. finally Not Executed on JVM Crash
class Demo {
public static void main(String[] args) {
try {
Runtime.getRuntime().halt(0);
} finally {
System.out.println("Finally");
}
}
}
Explanation
JVM halt → no cleanup
14. finally with throw
class Demo {
static void test() {
try {
throw new RuntimeException();
} finally {
System.out.println("Finally");
}
}
public static void main(String[] args) {
test();
}
}
Output
Finally
Exception in thread "main" java.lang.RuntimeException
15. finally with throw Overrides Exception
class Demo {
static void test() {
try {
throw new ArithmeticException();
} finally {
throw new NullPointerException();
}
}
public static void main(String[] args) {
test();
}
}
Explanation
finally exception overrides try exception
16. finally with Loop
class Demo {
public static void main(String[] args) {
for (int i = 1; i <= 3; i++) {
try {
System.out.println(i);
} finally {
System.out.println("Finally");
}
}
}
}
Output
1
Finally
2
Finally
3
Finally
17. finally in Method Call Stack
class Demo {
static void m1() {
try {
m2();
} finally {
System.out.println("Finally in m1");
}
}
static void m2() {
int a = 10 / 0;
}
public static void main(String[] args) {
try {
m1();
} catch (Exception e) {
System.out.println("Exception caught");
}
}
}
Output
Finally in m1
Exception caught
18. finally with break
class Demo {
public static void main(String[] args) {
while (true) {
try {
break;
} finally {
System.out.println("Finally");
}
}
}
}
Output
Finally
19. finally with continue
class Demo {
public static void main(String[] args) {
for (int i = 1; i <= 2; i++) {
try {
continue;
} finally {
System.out.println("Finally " + i);
}
}
}
}
Output
Finally 1
Finally 2
20. Interview Summary – finally Block
class Demo {
public static void main(String[] args) {
try {
int a = 10 / 0;
} catch (Exception e) {
System.out.println("Catch");
} finally {
System.out.println("Cleanup");
}
}
}
Key Points
- Executes almost always
- Used for cleanup
- Overrides return and exceptions if present
- Not executed only on JVM termination
Output
Catch
Cleanup