By WebNest Studio Engineering Team
Java - Core Tutorial
Final vs Finally vs finalize()
"final", "finally", and "finalize()" look similar and are a classic source of confusion for Java learners, but they belong to three completely unrelated parts of the language: a keyword that restricts modification, a block that guarantees cleanup code runs, and a deprecated method once tied to garbage collection.
Knowing the difference precisely — not just that "they're different" — is a frequent interview question and also affects real code decisions, especially now that finalize() is deprecated and should not be used in new code.
Why it matters
These three names look related and have nothing to do with each other: a keyword, a block and a deprecated method. Being asked to distinguish them is one of the oldest Java interview questions. The useful part is the last one — understanding why finalize() was abandoned tells you how resources should really be released.
final — a Keyword
final is a modifier applied to variables, methods, or classes to restrict change.
- A
finalvariable can be assigned exactly once; after that its value (or, for a reference, the object it points to) cannot be reassigned. - A
finalmethod cannot be overridden by a subclass. - A
finalclass cannot be extended/subclassed at all (e.g.StringandIntegerare final classes).
finally — a Block
finally is a block attached to a try statement (try { ... } finally { ... }, with or without a catch) that is guaranteed to execute after the try block finishes, whether it completed normally, threw an exception, or executed a return statement. It exists specifically for cleanup code — closing files, releasing locks, closing database connections — that must run regardless of what happened in the try block.
finalize() — a Deprecated Method
finalize() is a protected method defined on Object that the garbage collector historically called on an object right before reclaiming its memory, giving it one last chance to release resources. In practice it was unreliable: there was no guarantee about when, or even if, it would run before the JVM exited, and it made garbage collection slower and harder to reason about. Object.finalize() has been deprecated since Java 9 and was removed from later JDK versions entirely. The modern replacement for deterministic cleanup is try-with-resources together with the AutoCloseable interface, which closes a resource predictably at the end of the try block instead of at some unpredictable future garbage-collection cycle.
Examples
final variable, final method, and final class in one file
final class ImmutablePoint { // final class: cannot be extended
final int x; // final field: assigned once, in the constructor
final int y;
ImmutablePoint(int x, int y) {
this.x = x;
this.y = y;
}
final String describe() { // final method: cannot be overridden
return "(" + x + ", " + y + ")";
}
}
public class FinalDemo {
public static void main(String[] args) {
ImmutablePoint p = new ImmutablePoint(3, 4);
System.out.println(p.describe());
}
}
(3, 4)
finally always runs, and try-with-resources replaces the old finalize() approach to cleanup
public class FinallyVsCleanupDemo {
static int divide(int a, int b) {
try {
return a / b;
} finally {
System.out.println("finally block runs even though we are returning");
}
}
public static void main(String[] args) {
try {
// divide() runs, and its finally prints, before println prints the result
System.out.println("Result: " + divide(10, 2));
System.out.println("Result: " + divide(10, 0));
} catch (ArithmeticException e) {
System.out.println("Caught: " + e.getMessage());
}
// Modern cleanup pattern: AutoCloseable + try-with-resources (not finalize())
try (java.io.StringWriter writer = new java.io.StringWriter()) {
writer.write("hello");
System.out.println("Wrote: " + writer.toString());
} catch (java.io.IOException e) {
System.out.println("IO error: " + e.getMessage());
}
// writer.close() is called automatically here, deterministically
}
}
finally block runs even though we are returning
Result: 5
finally block runs even though we are returning
Caught: / by zero
Wrote: hello
Common Mistakes
- Confusing "final" with "finally" purely because of the similar spelling — one is a modifier, the other is a block.
- Relying on finalize() to release important resources like file handles or sockets — it is deprecated, unreliable in timing, and may never run before JVM exit.
- Forgetting that a final reference variable only locks the reference itself, not the object's internal state — a final List reference can still have elements added to it.
- Assuming a finally block can be skipped by a return in the try block — finally still executes before the method actually returns.
Exercise
Complete Connection so it can be used in a try-with-resources statement. Its close() method should print closed, and it must be called automatically.
Expected output: open, work, closed
// TODO: make Connection implement AutoCloseable and add close()
class Connection {
Connection() {
System.out.println("open");
}
void work() {
System.out.println("work");
}
}
public class ResourceDemo {
public static void main(String[] args) {
try (Connection connection = new Connection()) {
connection.work();
}
}
}
Show hints
- A class used in try-with-resources must implement
AutoCloseable. - Declare
public void close()withoutthrows Exception, so the caller needs no catch block.
Show solution
class Connection implements AutoCloseable {
Connection() {
System.out.println("open");
}
void work() {
System.out.println("work");
}
@Override
public void close() {
System.out.println("closed");
}
}
public class ResourceDemo {
public static void main(String[] args) {
try (Connection connection = new Connection()) {
connection.work();
}
}
}
Quick quiz
1. Which of the three is a block of code attached to a try statement?
- A. final
- B. finalize
- C. finally
- D. None of them
Show answer
C. finally is the block that runs after try and catch. final is a keyword and finalize() is a method of Object.
2. What is the status of finalize() in modern Java?
- A. It is the recommended way to release resources
- B. It was removed in Java 8
- C. It is deprecated and should not be used
- D. It is required in every class
Show answer
C. finalize() has been deprecated since Java 9 and is marked for removal. Use try-with-resources instead.
3. What does final mean when applied to a local variable?
- A. It is cleaned up automatically
- B. It cannot be read
- C. It is shared between threads
- D. It can be assigned only once
Show answer
D. A final variable cannot be reassigned after its first assignment.
Interview questions
What is the difference between final, finally and finalize?
Show answer
final is a keyword: a final variable cannot be reassigned, a final method cannot be overridden, and a final class cannot be extended. finally is a block that follows try and catch and runs whether or not an exception occurred, used for cleanup. finalize() is a method of Object that the garbage collector could call before reclaiming an object; it is deprecated.
Why was finalize() deprecated?
Show answer
Because it is unreliable. There is no guarantee when it runs, or that it runs at all, so it cannot be trusted to release files or connections. It also slows garbage collection and can accidentally keep an object alive. The replacement is to implement AutoCloseable and use try-with-resources, which releases the resource at a known point.
Key Points to Remember
- final (keyword): locks a variable's value, prevents a method from being overridden, or prevents a class from being subclassed.
- finally (block): a section of a try statement that always runs, used for guaranteed cleanup.
- finalize() (method): a deprecated Object method once invoked by the garbage collector before object reclamation; do not rely on it.
- Use try-with-resources and AutoCloseable for deterministic, modern resource cleanup instead of finalize().
Practice in the playground
Write and run your own code for this topic, or start from the exercise or an example. Runs plain Java 17. Frameworks such as Spring, and databases, are not available here. Your code for each topic is kept in this browser.
Run the examples
Change an input, predict the result, then compare it with the output. Explain why the result changes.
Written by
WebNest Studio Engineering Team
Practical lessons from developers working with Java, Python, React, databases and production systems.
Led by Vansh Duggal, Founder, WebNest Studio · Full-stack & software engineering