Java 中广泛使用不可变类(Immutable Class),核心原因是:不可变对象更安全、更简单、更容易在并发和多模块系统中正确使用。下面从多个角度系统说明“为什么 Java 要用不可变类”。
不可变类:对象一旦创建,其状态(字段值)就不能再被修改。
典型特征:
final 修饰(防止被继承破坏行为)private final 修饰示例:
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; }
}
不可变对象是天然线程安全的:
// 无需 synchronized
User user = new User("Tom", 18);
对比可变对象:
✅ 不可变对象 = 无并发问题
不可变对象:
可变对象:
user.setAge(20); // 悄悄改变了状态
不可变对象:
User olderUser = user.withAge(20);
✅ 状态变化显式可见
不可变对象:
Map<User, String> cache = new HashMap<>();
cache.put(user, "info");
如果用可变对象做 key:
✅ 不可变对象是优秀的 Map / Set 元素
Java 中大量核心 API 依赖不可变类:
| 类型 | 不可变原因 |
|---|---|
String |
常量池、线程安全 |
Integer |
缓存、共享 |
BigDecimal |
精确计算 |
例如:
String s = "abc";
s += "d"; // 新对象,不是修改原对象
✅ 没有不可变类,Java 基础库会极其危险
不可变对象符合:
list.stream()
.map(User::name)
.collect(Collectors.toList());
✅ 不可变对象是 FP 的基础
如果对象可变,可能被外部篡改:
class User {
Date birthday; // 可变
}
外部可以:
user.getBirthday().setTime(0);
如果:
private final LocalDate birthday; // 不可变
✅ 不可变 = 防御性安全
一句话总结:
在并发、共享、复杂系统中,不可变对象成本最低、风险最小。
| 对比维度 | 可变对象 | 不可变对象 |
|---|---|---|
| 线程安全 | ❌ 需要锁 | ✅ 天然 |
| 并发复杂度 | 高 | 低 |
| 可预测性 | 差 | 好 |
| 可共享性 | 差 | 好 |
| Bug 风险 | 高 | 低 |
缺点:
适合:
不适合:
✅ 优先使用不可变类的场景:
Java 使用不可变类,是为了用“限制变化”来换取“系统安全、简洁和可维护性”,尤其是在并发时代,这是最划算的设计选择。
如果你愿意,我可以:
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。