在 Java 中,不可变类(Immutable Class)指对象一旦创建,其状态(字段值)就不能再被修改。典型代表是 String、Integer、LocalDate 等。
下面从适合使用不可变类的场景和原因两个角度来说明。
不可变对象是天然线程安全的,不需要加锁。
✅ 场景:
✅ 好处:
synchronized// 多个线程同时读,不需要任何同步
public final class User {
private final String name;
private final int age;
}
不可变对象 hashCode 稳定,不会破坏集合结构。
✅ 场景:
❌ 可变对象做 key 的风险:
Map<UserId, UserInfo> cache = new HashMap<>();
配置一旦加载,不应再被修改。
✅ 场景:
public final class AppConfig {
private final String env;
private final int port;
}
只关心“值是什么”,不关心身份。
✅ 场景:
Money price = new Money(100);
特点:
equals() 比较无副作用,结果可预测。
✅ 场景:
list.stream()
.map(x -> new Result(x))
.collect(...)
对象可安全共享,减少创建成本。
✅ 场景:
Integer a = 100;
Integer b = 100;
// a == b(缓存)
返回内部数据给调用方时,防止被篡改。
✅ 场景:
public User getUser() {
return new User(name, age); // 而不是暴露可变对象
}
| 场景 | 原因 |
|---|---|
| 频繁修改对象状态 | 每次修改都会创建新对象,性能差 |
| 大对象、状态复杂 | 拷贝成本高 |
| 需要标识变化过程 | 需要记录“变化历史” |
✅ 这类场景更适合可变对象 + 明确生命周期管理
✅ 默认优先使用不可变类,除非你有明确理由不用它。
这是《Effective Java》的核心建议之一。
public final class User {
private final String name;
private final int age;
public User(String name, int age) {
this.name = name;
this.age = age;
}
public String name() { return name; }
public int age() { return age; }
}
要点:
final classprivate final只要对象“创建后不应该再改变”,就优先考虑不可变类,尤其是并发、缓存、值对象、配置、key 等场景。
如果你愿意,我也可以帮你判断某个具体业务对象是否应该设计成不可变类。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。