中 基础
final关键字#
一句话答案#
final 修饰类不可继承、方法不可重写、变量不可重新赋值(引用不可变但对象内容可变)。
核心要点
final 可以修饰三种目标,语义各不相同:
1. 修饰变量
- 基本类型:值不可变(常量)
- 引用类型:引用地址不可变,但引用指向的对象内容可以改变
final int x = 10; // x 不能被重新赋值
final List<String> list = new ArrayList<>();
list.add("ok"); // 合法,list 指向的对象内容可变
list = new ArrayList<>(); // 编译报错,引用不可重新指向java2. 修饰方法
- 该方法不能被子类重写(Override)
- 常用于模板方法中需要固定的步骤
3. 修饰类
- 该类不能被继承
- 典型:
String、Integer、Math都是final类 - 好处:保证安全性(不被恶意子类覆盖),JIT 可做更激进的内联优化
补充:final 与线程安全
final字段在构造函数完成后对其他线程可见(JMM 保证),不需要额外同步- 这是
String不可变且线程安全的基础之一
面试回答(2分钟版)
final关键字可以修饰三种目标,语义各不相同。修饰类表示该类不可被继承,典型的如String、Integer、Math都是final类,目的是保证不可变性和安全性,防止被恶意子类覆盖行为。修饰方法表示不可被子类重写,常用于模板方法模式中需要固定的步骤,但注意final方法可以被重载。修饰变量表示不可被重新赋值,这是面试最容易挖坑的地方:基本类型的final变量值不可变就是常量,但引用类型的final变量只是引用地址不可变,引用指向的对象内容仍然可以修改——比如final List仍然可以add元素,只是不能让引用指向新的List对象。final还有一个和并发相关的重要特性:JMM保证final字段在构造函数完成后对其他线程可见,不需要额外的同步措施,这是String线程安全的基础之一。final方法早期是为了让JVM做方法内联优化性能,但现在JIT编译器已经能自动优化,所以final方法主要是表达设计意图而非性能考量。
追问与易错
追问方向:
- “final 修饰引用类型意味着什么?”→ 引用地址不可变(不能指向新对象),但引用指向的对象内容仍可修改,如 final List 仍可 add 元素
- “final 方法能被重载吗?”→ 可以重载(方法签名不同),不能重写(Override);final 限制的是子类覆盖,不影响同类中的方法重载
- “为什么 String 是 final 类?”→ 保证不可变性:防止子类重写方法破坏不可变契约,确保线程安全、hashCode 缓存、字符串常量池复用和安全性
易错点:
- ❌ “final 变量就是常量”——引用类型的 final 变量指向的对象内容仍可修改
- ❌ “final 方法是为了性能”——JDK 早期是为了内联,现在 JIT 自动优化,主要是设计意图