Definition
Three unrelated concepts that share a name:
- final is a keyword for immutability. Prevents variable reassignment, method overriding, or class extension.
- finally is a block in
try-catch-finallythat always executes, whether or not an exception was thrown. Used for cleanup. - finalize() is a method on
Objectcalled by the garbage collector before reclaiming an object. Deprecated since Java 9. Never rely on it.
final is a permanent seal on a document – once sealed, it cannot be changed. finally is the bank clerk who always locks the vault at closing time, whether or not there was a problem during the day. finalize is a retired security guard who sometimes checks the building before demolition – but he is unreliable and has been replaced.
Understanding the Concepts
What is final?
// final variable: cannot be reassigned
final String accountId = "SAV2001";
// accountId = "CUR3001"; // COMPILE ERROR
// final method: cannot be overridden
public final BigDecimal getBalance() { return balance; }
// final class: cannot be extended
public final class TransactionId { ... }
See Q6 for the complete explanation of final.
What is finally?
finally is a block that always executes after try-catch, whether or not an exception was thrown.
Connection conn = null;
try {
conn = dataSource.getConnection();
// do database work
} catch (SQLException e) {
log.severe("DB error: " + e.getMessage());
} finally {
// ALWAYS runs – cleanup
if (conn != null) {
try { conn.close(); } catch (SQLException e) { /* log */ }
}
}
- finally runs even if:
- The try block completes normally
- An exception is thrown and caught
- An exception is thrown and NOT caught (finally runs, then the exception propagates)
- The try block has a
returnstatement (finally runs before the return)
What is the modern replacement for finally?
try-with-resources (Java 7+) automatically closes resources that implement AutoCloseable:
// Modern: no finally needed
try (Connection conn = dataSource.getConnection();
PreparedStatement ps = conn.prepareStatement(sql)) {
// do work
} catch (SQLException e) {
log.severe("DB error: " + e.getMessage());
}
// conn and ps are automatically closed here
Prefer try-with-resources over try-finally for all closeable resources.
What is finalize()?
finalize() is a method on Object that the garbage collector may call before reclaiming an object. It was intended for cleanup of native resources.
// DEPRECATED: do not use this
@Override
protected void finalize() throws Throwable {
// close native resource
super.finalize();
}
Why it is bad:
- Not guaranteed to run. The GC may never call it.
- Timing is unpredictable. You cannot control when (or if) it runs.
- Performance penalty. Objects with finalizers are slower to collect.
- Deprecated since Java 9. Removed for good reason.
Modern replacement: java.lang.ref.Cleaner (Java 9+) or try-with-resources.
Summary comparison
| Feature | final | finally | finalize() |
|---|---|---|---|
| What is it | Keyword | Block | Method |
| Purpose | Prevent change | Guarantee cleanup | GC callback |
| Used with | Variables, methods, classes | try-catch | Object lifecycle |
| Status | Active, use it | Active, prefer try-with-resources | Deprecated since Java 9 |
What are common mistakes?
- Confusing the three. They have nothing in common except spelling. Interviewers test this.
- Relying on finalize() for resource cleanup. Use try-with-resources instead.
- Forgetting that finally runs even after return.
try { return x; } finally { cleanup(); }runs cleanup() before returning.
What should a senior engineer know?
- finally can suppress exceptions. If both try and finally throw, the try's exception is lost. Use try-with-resources which handles suppressed exceptions properly.
- System.exit() in try prevents finally.
System.exit(0)in the try block terminates the JVM immediately – finally does not run. - Cleaner API (Java 9+) is the proper replacement for finalize(). Register a cleaning action with
Cleaner.create().register(obj, action).
Visual Overview
final: keyword → prevents reassignment / override / extension
finally: block → always runs after try, used for cleanup
finalize(): method → GC callback, deprecated, never use
final: final int x = 10; x = 20; → COMPILE ERROR
finally: try { ... } finally { cleanup(); } → always runs
finalize: @Override protected void finalize() → deprecated
Modern replacements:
finally → try-with-resources (AutoCloseable)
finalize → Cleaner API (Java 9+)
Key Takeaway
final, finally, and finalize() are three completely unrelated concepts that happen to share a name. final is a keyword that prevents change: a final variable cannot be reassigned, a final method cannot be overridden, a final class cannot be extended. finally is a block that always executes after try-catch, used for cleanup code. finalize() is a deprecated method that the garbage collector may call before reclaiming an object – it is unreliable, slow, and should never be used.
In modern Java, prefer try-with-resources over finally for closing resources, and the Cleaner API over finalize() for native resource cleanup.
One sentence to remember: final prevents change, finally guarantees cleanup, finalize is deprecated – they have nothing in common except spelling.
---