00:00

final vs finally vs finalize in Java – Differences Explained

Last updated: 6 min read

final, finally and finalize sound alike, which makes them a favourite interview question, but they have nothing in common except their spelling:

  • final is 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.
  • finally is a block of a try statement that always runs after the try and catch blocks.
  • finalize() was a method of Object called by the garbage collector before reclaiming an object. It is deprecated for removal and should not be used.

1. Comparison Table

Aspectfinalfinallyfinalize()
What it isKeyword / modifierBlock in a try statementMethod of java.lang.Object
Applies toVariables, methods, classestry-catch statementsObjects (overridden in a class)
PurposePrevent reassignment, overriding or inheritanceRun clean-up code in every caseClean up before garbage collection (obsolete)
When it takes effectCompile time (enforced by the compiler)Every time the try statement finishesMaybe, at an unpredictable time, or never
StatusWidely usedWidely usedDeprecated since Java 9, for removal since Java 18
Modern alternative–try-with-resources for resourcesAutoCloseable + try-with-resources, or Cleaner

2. final: Prevent Change

FinalDemo.java
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);
    }
}
Output
Shape circle, tax rate 0.18, limit 3
  • final variable: can be assigned only once; static final fields are constants.
  • final method: subclasses cannot override it.
  • final class: cannot be extended (like String and Integer).

See final keyword in Java.

3. finally: Always Run

FinallyDemo.java
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);
    }
}
Output
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 this somewhere.
  • It creates security and reliability risks.

It was deprecated in Java 9 and marked "for removal" in Java 18 (JEP 421). Use these instead:

CleanerDemo.java
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");
    }
}
Output
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, if close() 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

  • final is a modifier for variables, methods and classes that prevents change.
  • finally is 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 Cleaner as a safety net) instead of finalize().

Related Tutorials