不可变类需满足:1. 所有字段private final;2. 不提供修改方法,getter返回不可变视图或副本;3. 构造器对可变参数做防御性拷贝;4. 类声明为final。

设计一个不可变类,核心是确保对象一旦创建,其状态(即所有字段)在生命周期内**无法被修改**。Java 中典型的不可变类如 String、Integer、LocalDate 等,它们的安全性依赖于严格的封装和防御性编程。
1. 所有字段必须是 private final
这是不可变性的基础。用 private 阻止外部访问,用 final 保证构造后不能重新赋值。
例如:
private final String name;
private final int age;
private final List
⚠️ 注意:final 只保证引用不改变,不保证引用的对象内容不可变(比如 ArrayList 本身仍可 add/remove)。所以还需下一步处理。
2. 不提供任何修改状态的方法(无 setter、无 add/remove 等)
禁止暴露任何能改变内部字段的方法。连看似无害的「修改集合」方法也要避免。
✅ 正确做法:
- 只提供 getter(且返回副本或不可变视图)
- 若字段是可变对象(如
ArrayList),getter 中返回Collections.unmodifiableList()或新拷贝(如new ArrayList(this.hobbies)) - 构造器中对传入的可变参数做防御性拷贝(见下一点)
3. 构造器中进行防御性拷贝(Defensive Copy)
防止调用方在构造后通过原始引用偷偷修改内部状态。
示例:
public Person(String name, int age, List
this.name = Objects.requireNonNull(name);
this.age = age;
this.hobbies = new ArrayList(Objects.requireNonNull(hobbies)); // 防御性拷贝
}
如果传入的是 Arrays.asList(...) 或其他共享列表,不拷贝就会导致外部可修改内部状态。
4. 类本身声明为 final(推荐)
防止子类通过继承破坏不可变性(比如重写方法、添加可变字段)。
✅ 声明:public final class Person { ... }
如果不加 final,即使当前类不可变,子类可能引入可变状态或覆盖行为,削弱不可变保证。
不复杂但容易忽略。关键不是“写完不改”,而是从设计上切断所有修改路径——封字段、断引用、拷数据、锁继承。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











