final 是 Java 中用于表达“不可变性”(Immutability)的关键字,可修饰变量、方法和类。其核心作用是限制变更,提升代码安全性与可读性。
1. final 修饰变量
局部变量
- 必须在声明时或使用前显式初始化;
- 一旦赋值,不能重新赋值;
- 若被匿名内部类或 Lambda 表达式捕获,必须是 effectively final(实质上不可变),显式
final非必需但可增强语义。
成员变量(字段)
- 只能在声明处或构造器中赋值一次;
- 对象构造完成后,引用不可更改;
- 注意:
final仅锁定引用,不阻止修改对象内部状态(如final List仍可add())。
引用类型 vs 基本类型
final int x = 10;→x的值不可变;final StringBuilder sb = new StringBuilder();→sb引用不可变,但sb.append()允许(对象内容可变)。
2. final 修饰方法
- 禁止子类重写(override);
- 可用于保护关键逻辑不被覆盖;
- 不影响继承和调用。
3. final 修饰类
- 禁止被继承;
- 常用于设计不可变类或安全敏感类(如
String、Integer); - 提升安全性与 JVM 优化潜力。
4. final 与线程安全
final本身不等于线程安全;- 它保证:
- 引用不可变;
- 在 Java 内存模型(JMM)下,正确构造的对象其
final字段对所有线程立即可见;
- 线程安全性最终取决于所引用对象是否线程安全:
- ✅
final String s = "x"→ 线程安全(String不可变); - ❌
final List<String> list = new ArrayList<>()+ 多线程修改 → 非线程安全。
- ✅
5. 最佳实践
- 优先将成员变量声明为
final,尤其是依赖注入字段; - 构造不可变对象时,所有字段应为
final; - 结合不可变集合(如
List.of()、Collections.unmodifiableList())实现真正不可变状态; - 避免误认为
final能自动保证并发安全。
核心原则:
final锁定的是“标识符的绑定”,而非“对象的内容”。理解这一点,是正确使用final的关键。