final关键字可用于变量、方法、类:1.变量——基本类型值不可变,引用类型引用不可变但对象状态可变;2.方法——不能被子类重写;3.类——不能被继承。

final 关键字在 Java 中用于声明“不可变”的变量、方法或类。对于变量,它表示该变量一旦被赋值,就不能再指向其他对象或值——但要注意:这不等于对象本身不可变,而是引用不可重定向。
定义基本类型 final 变量
基本类型(如 int、boolean、double 等)用 final 修饰后,值完全固定,后续无法修改:
final int MAX_COUNT = 100; // MAX_COUNT = 200; // 编译错误!
- 必须在声明时或构造块/构造方法中完成初始化(否则编译报错)
- 适合定义常量,习惯上使用全大写+下划线命名(如 DEFAULT_TIMEOUT)
定义引用类型 final 变量
对对象引用使用 final,只保证该引用不能再指向另一个对象,但对象内部状态仍可能改变:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
final List<String> names = new ArrayList<>();
names.add("Alice"); // ✅ 允许:修改对象内容
// names = new ArrayList<>(); // ❌ 编译错误:不能重新赋值引用
- 若需真正不可变对象,应配合不可变集合(如 java.util.Collections.unmodifiableList)或使用 ImmutableList(Guava)
- 常见误区:误以为 final List 就是只读列表,实际只是“引用锁定”
final 变量的初始化时机
final 变量有三种合法初始化方式:
立即学习“Java免费学习笔记(深入)”;
- 声明时直接赋值(最常见)
- 在实例初始化块中赋值(适用于需要多行逻辑计算的场景)
- 在每个构造方法中显式赋值(确保所有对象创建路径都初始化)
public class Config {
final String host;
final int port;
public Config(String host, int port) {
this.host = host; // ✅ 必须在此赋值
this.port = port; // ✅ 否则编译失败
}
}
和不可变类的关系
仅靠 final 字段不足以让一个类不可变。完整不可变类还需满足:
- 类本身用 final 修饰(防止被继承并破坏封装)
- 所有字段为 private final
- 不提供修改状态的方法(setter、可变集合的 add/remove 等)
- 若含可变对象字段(如 Date、ArrayList),需防御性拷贝(defensive copy)
public final class Person {
private final String name;
private final Date birthDate; // Date 是可变的!
public Person(String name, Date birthDate) {
this.name = name;
// 防御性拷贝,避免外部修改影响内部状态
this.birthDate = new Date(birthDate.getTime());
}
public Date getBirthDate() {
return new Date(birthDate.getTime()); // 返回副本
}
}
不复杂但容易忽略。关键在分清“引用不可变”和“对象不可变”的区别。

















