Ba ngữ cảnh, cùng ý "không thể đổi" — nhưng "đổi" gì thì phụ thuộc:
java
final class String { ... } // 1. class — không extend được
class Base {
final void render() { ... } // 2. method — subclass không override được
}
final int MAX = 100; // 3. variable — không gán lại được
final List<String> names = new ArrayList<>();
names.add("Ada"); // OK — reference không đổi, NỘI DUNG vẫn đổi được
names = new ArrayList<>(); // ❌ compile errorfinal class— chống extends (vdString,Integer). Bảo vệ invariant + cho JIT inline mạnh hơn.final method— chống override. Cho template method khung không cho phép thay đổi.final variable— gán đúng 1 lần. Field phải gán ở khai báo/constructor.static final= hằng số (UPPERCASE).
Bẫy: final trên reference chỉ khoá biến — object bên trong vẫn mutate được. Muốn bất biến thật, dùng List.copyOf(...).
Liên quan: record field ngầm là final; sealed (Java 17+) chặt hơn final cho hierarchy có giới hạn subtype.