final means cannot be changed after it is set: a variable can't be reassigned, a method can't be overridden, a class can't be extended.
final in three places
| Applied to | Effect | Example |
|---|---|---|
| Variable (local, field, parameter) | Assigned exactly once | final int max = 10; |
| Method | Cannot be overridden by subclasses | final void audit() |
| Class | Cannot be extended | String, Integer, all records |
Final variables
import java.util.ArrayList;
import java.util.List;
public class Main {
static final double TAX_RATE = 0.18; // constant: static final, UPPER_CASE
public static void main(String[] args) {
final List<String> names = new ArrayList<>();
names.add("Asha"); // OK: the object is mutable
names.add("Ravi");
// names = new ArrayList<>(); // error: cannot assign a value to final variable names
System.out.println(names);
final int limit; // "blank final": assigned once, later
limit = args.length > 0 ? 5 : 10;
System.out.println(limit + " " + TAX_RATE);
}
}[Asha, Ravi]
10 0.18Blank finals must be assigned in every constructor
class Account {
private final String id;
Account(String id) { this.id = id; }
Account() { } // forgot to assign id
}Main.java:4: error: variable id might not have been initialized
Account() { } // forgot to assign id
^Effectively final
A local variable that is never reassigned is effectively final even without the keyword. Lambdas and anonymous/local classes may only capture effectively final locals.
public class Main {
public static void main(String[] args) {
int base = 100; // never reassigned → effectively final
Runnable r = () -> System.out.println(base + 1);
r.run();
}
}101public class Main {
public static void main(String[] args) {
int count = 0;
Runnable r = () -> System.out.println(count);
count++; // makes count NOT effectively final
r.run();
}
}Main.java:4: error: local variables referenced from a lambda expression must be final or effectively final
Runnable r = () -> System.out.println(count);
^Final methods and classes
A
finalmethod keeps its behaviour fixed in every subclass — good for security-sensitive or template-method steps.A
finalclass cannot be subclassed:String, the wrapper classes,LocalDate, everyrecordandenum(without bodies).privatemethods are implicitly final (they aren't inherited, so nothing can override them).abstractandfinaltogether are illegal: one demands a subclass, the other forbids it.
final vs finally vs finalize
| Keyword | What it is |
|---|---|
final | Modifier: no reassignment / overriding / extending. |
finally | Block after try/catch that always runs (cleanup). |
finalize() | Object method once called by the GC before reclaiming an object — deprecated for removal since Java 18; use try-with-resources or Cleaner. |
Does final make an object immutable?
Why is String final?
Can a final variable be initialised later?