final, finally, and finalize look like siblings.
They are not.
I have seen beginners mix them up because tutorials explain them as definitions. I think they make more sense if you connect each one to the bug it prevents.
Quick Map
| Keyword / method | What it protects against |
|---|---|
final |
accidental reassignment, override, or inheritance |
finally |
cleanup code being skipped |
finalize |
mostly historical cleanup confusion |
The uncomfortable truth: you should understand finalize, but you probably should not use it.
final: Stop Accidental Change
Use final when a value or behavior should not be changed after it is set.
public class RateLimiter {
private final int maxRequests;
public RateLimiter(int maxRequests) {
this.maxRequests = maxRequests;
}
public boolean allow(int currentRequests) {
return currentRequests < maxRequests;
}
}
Here maxRequests cannot be reassigned after construction. That is boring, and boring is good.
You can also use final on methods:
class BaseService {
public final void audit() {
System.out.println("audit event written");
}
}
A subclass cannot override audit(). I would use this sparingly. If you need final everywhere, your inheritance design may already be too clever.
And on classes:
public final class StringUtils {
private StringUtils() {}
}
This says: do not extend this class.
finally: Cleanup Even When Things Break
finally runs whether the try block succeeds or throws.
Old-style file handling:
FileReader reader = null;
try {
reader = new FileReader("config.txt");
// read file
} catch (IOException e) {
System.out.println("read failed: " + e.getMessage());
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException ignored) {
// logging would be better in production
}
}
}
This works, but modern Java gives you a cleaner option:
try (FileReader reader = new FileReader("config.txt")) {
// read file
} catch (IOException e) {
System.out.println("read failed: " + e.getMessage());
}
That is try-with-resources. In most production code, I would prefer it over a manual finally.
Still, finally matters when cleanup is not an AutoCloseable resource:
lock.lock();
try {
updateSharedState();
} finally {
lock.unlock();
}
This is the real bug finally prevents: a lock stays locked because an exception jumped over your cleanup line.
finalize: Know It, Then Avoid It
finalize() was intended to run before garbage collection reclaims an object.
@Override
protected void finalize() throws Throwable {
System.out.println("cleanup before GC");
}
Do not build production cleanup around this.
Why?
- You do not control when GC runs.
- It may run much later than expected.
- It adds performance and reliability problems.
- It has been deprecated for removal in modern Java.
If you need cleanup, use AutoCloseable:
class ConnectionHandle implements AutoCloseable {
@Override
public void close() {
System.out.println("connection closed");
}
}
try (ConnectionHandle handle = new ConnectionHandle()) {
System.out.println("using connection");
}
This is explicit. You can reason about it. Production code likes that.
The Rule I Use
- Use
finalto make intent harder to accidentally break. - Use
finallywhen cleanup must happen even after exceptions. - Avoid
finalize; use explicit cleanup instead.
Final Thought
These three names are confusing, but the responsibilities are not.
final is about preventing change. finally is about guaranteed cleanup. finalize is a legacy GC hook you should not lean on.
Which Java keyword confused you the most when you first learned backend development?
Top comments (3)
Consider the following Java program:
Will this compile? Runs without errors? Does this print "Value of i is 10"?
More about final variables at final Variables (Java Language Specification)
finalize() and try-with-resources are not really related.
Finalize() could be used for things such as making sure that a temp file was deleted when no longer used and other such cleanup applications.
In modern Java the same can be accomplished with Phantom references as shown here:
stackoverflow.com/questions/433118...
My new post for Java developers ✨
Hope this help. Thank you 🌻
Top 10 GitHub repositories for Java developers ✨
Sáng Minh Trần ・ May 26