final vs finally vs finalize in Java – Differences Explained
final, finally and finalize sound alike, which makes them a favourite interview question, but they have nothing in common except their spelling:
finalis a keyword (modifier) that prevents change: a final variable cannot be reassigned, a final method cannot be overridden, and a final class cannot be extended.finallyis a block of a try statement that always runs after the try and catch blocks.finalize()was a method ofObjectcalled by the garbage collector before reclaiming an object. It is deprecated for removal and should not be used.
1. Comparison Table
| Aspect | final | finally | finalize() |
|---|---|---|---|
| What it is | Keyword / modifier | Block in a try statement | Method of java.lang.Object |
| Applies to | Variables, methods, classes | try-catch statements | Objects (overridden in a class) |
| Purpose | Prevent reassignment, overriding or inheritance | Run clean-up code in every case | Clean up before garbage collection (obsolete) |
| When it takes effect | Compile time (enforced by the compiler) | Every time the try statement finishes | Maybe, at an unpredictable time, or never |
| Status | Widely used | Widely used | Deprecated since Java 9, for removal since Java 18 |
| Modern alternative | – | try-with-resources for resources | AutoCloseable + try-with-resources, or Cleaner |
2. final: Prevent Change
public class FinalDemo {
static final double TAX_RATE = 0.18; // final variable: a constant
static class Shape {
final String name; // final field: set once in the constructor
Shape(String name) { this.name = name; }
final String describe() { // final method: cannot be overridden
return "Shape " + name;
}
}
static final class Circle extends Shape { // final class: cannot be extended
Circle() { super("circle"); }
}
public static void main(String[] args) {
final int limit = 3;
// limit = 4; // compile error: cannot assign a value to final variable
Circle c = new Circle();
System.out.println(c.describe() + ", tax rate " + TAX_RATE + ", limit " + limit);
}
}
Shape circle, tax rate 0.18, limit 3
- final variable: can be assigned only once;
static finalfields are constants. - final method: subclasses cannot override it.
- final class: cannot be extended (like
StringandInteger).
3. finally: Always Run
public class FinallyDemo {
static void process(int value) {
try {
System.out.println("processing " + value + " -> " + (100 / value));
} catch (ArithmeticException e) {
System.out.println("error: " + e.getMessage());
} finally {
System.out.println("finally: clean-up for " + value); // always runs
}
}
public static void main(String[] args) {
process(4);
process(0);
}
}
processing 4 -> 25 finally: clean-up for 4 error: / by zero finally: clean-up for 0
The finally block ran both after success and after the exception. It is used for clean-up such as releasing locks. See finally block in Java.
4. finalize(): Deprecated, Do Not Use
protected void finalize() throws Throwable was meant to let objects clean up before the garbage collector removed them. In practice it caused many problems:
- There is no guarantee when it runs, or whether it runs at all.
- It slows down garbage collection and can delay freeing memory.
- Exceptions thrown in it are silently ignored.
- It can "resurrect" objects by storing
thissomewhere. - It creates security and reliability risks.
It was deprecated in Java 9 and marked "for removal" in Java 18 (JEP 421). Use these instead:
import java.lang.ref.Cleaner;
public class CleanerDemo {
// finalize() is deprecated for removal; Cleaner (Java 9+) or try-with-resources replace it
private static final Cleaner CLEANER = Cleaner.create();
static class TempResource implements AutoCloseable {
private final Cleaner.Cleanable cleanable;
TempResource(String name) {
System.out.println("acquire " + name);
Runnable releaseAction = () -> System.out.println("release " + name); // must not reference 'this'
cleanable = CLEANER.register(this, releaseAction);
}
@Override public void close() { cleanable.clean(); } // explicit, predictable clean-up
}
public static void main(String[] args) {
try (TempResource r = new TempResource("buffer")) {
System.out.println("using resource");
}
System.out.println("done");
}
}
acquire buffer using resource release buffer done
- try-with-resources with
AutoCloseable: the main way to release resources deterministically. java.lang.ref.Cleaner(Java 9+): a safety net that runs an action when an object becomes unreachable, ifclose()was not called.
5. An Easy Way to Remember
- final → "fixed": the thing cannot change.
- finally → "in the end": runs at the end of try-catch, no matter what.
- finalize → "finalisation of an object": an old garbage-collection hook you should avoid.
6. Summary
finalis a modifier for variables, methods and classes that prevents change.finallyis a block that always runs after try and catch, used for clean-up.finalize()was an Object method for pre-GC clean-up; it is deprecated for removal.- Use try-with-resources (and
Cleaneras a safety net) instead offinalize().
Related Tutorials
Frequently Asked Questions (FAQ)
Q1. What is the difference between final, finally and finalize?
final is a modifier that prevents reassignment, overriding or inheritance. finally is a block that always runs after try-catch. finalize() is a deprecated Object method that the garbage collector could call before removing an object.
Q2. Is finalize() still available in Java?
It still exists in current versions but is deprecated for removal (since Java 18), and finalization can already be disabled with --finalization=disabled. Do not use it in new code.
Q3. Is finally a keyword?
Yes. finally is a reserved keyword used only in try statements.
Q4. Is finalize a keyword?
No. finalize is just the name of a method in java.lang.Object.
Q5. Does finally run before finalize?
They are unrelated. finally runs when a try statement ends; finalize() might run much later, during garbage collection, or never.
Q6. Can a final variable be changed in a finally block?
No. A final variable can be assigned only once, wherever that happens.
Q7. Is finalize() guaranteed to be called?
No. The JVM may never run it, for example if the program ends before the object is collected. This unreliability is one reason it was deprecated.
Q8. What replaces finalize()?
Implement AutoCloseable and use try-with-resources for deterministic clean-up. Use java.lang.ref.Cleaner as a fallback safety net.
Q9. Can a method be both final and static?
Yes, although static methods cannot be overridden anyway (only hidden), so final mainly prevents hiding in subclasses.
Q10. Can a finally block exist without catch?
Yes, a try-finally statement runs clean-up code while letting exceptions propagate.
Q11. Can a final class have final methods?
Yes, but it is redundant: since the class cannot be extended, none of its methods can be overridden anyway.
Q12. When does finally not execute?
When the JVM exits (for example via System.exit()) or crashes, or when the try block never finishes.
Q13. Why was finalize() deprecated?
Its timing was unpredictable, it hurt GC performance, it ignored exceptions, it could resurrect objects, and it created security risks. Better mechanisms exist.
Q14. What is the Cleaner class?
A java.lang.ref class (Java 9+) that registers a clean-up action to run when an object becomes phantom-reachable. The action must not reference the object itself.
Q15. Can I declare a constructor final?
No. Constructors are not inherited or overridden, so final is not allowed on them.
Q16. Does final make an object immutable?
No. A final reference cannot point to another object, but the object's own state can still change unless its class is designed to be immutable.
Q17. Is finally related to exceptions only?
It belongs to try statements, which are about exceptions, but it also runs when the try block ends normally or through return, break or continue.
Q18. What was the signature of finalize()?
protected void finalize() throws Throwable, declared in java.lang.Object and overridable by subclasses.
Q19. Can final be used with method parameters?
Yes. A final parameter cannot be reassigned inside the method. It is sometimes used for clarity or for older code that needed it for anonymous classes.
Q20. Which of the three is most used in modern Java?
final, very frequently, and finally, regularly. finalize() should not appear in modern code at all.