跳转至

final 的用途

一、三种用法

1. 修饰类

不能被继承:

public final class String {}

2. 修饰方法

不能被子类重写:

public final void method() {}

3. 修饰变量

变量只能赋值一次,变成常量:

final int x = 10;
x = 20;   // 编译错误

二、final 修饰变量的细节

基本类型

值不能改。

引用类型

引用不能改,但对象内容可以改:

final List<String> list = new ArrayList<>();
list.add("a");       // ✅ 可以
list = new ArrayList<>();  // ❌ 引用不能改

实例变量

必须在声明时或构造函数里赋值。

静态变量

必须在声明时或静态块里赋值。

局部变量

用一次前赋值即可。

三、final 参数

方法参数不能改:

public void method(final int x) {
    x = 10;   // 编译错误
}

四、为什么用 final

  1. 安全:防止子类篡改(String 不可变基础)。
  2. 性能:JIT 可以内联 final 方法。
  3. 线程安全:final 字段在构造完成后对其他线程可见(JMM 语义)。
  4. 设计约束:明确告诉调用者不要改。

五、final 与 immutable

String 不可变的基础: - class 是 final。 - value 数组是 private final。 - 不提供修改方法。

高频追问

  • final 方法一定 inline 吗?不一定,JIT 决定。
  • final 类里的方法默认是 final 吗?不是,只是不能被继承。