不可变对象的核心是彻底切断所有可变入口:字段全用private final修饰;引用类型需不可变或防御性拷贝;不提供修改方法;构造器防逸出;类应声明为final。

设计不可变对象的核心是:禁止外部修改对象状态,且内部状态一旦创建就不再改变。Java 中的 String、LocalDate、BigInteger 都是典型例子。实现的关键不在“写 final”,而在于**彻底切断所有可变入口**。
字段全部用 final 修饰并私有化
这是基础但不够。所有字段必须声明为 final,且访问权限为 private,防止子类继承后篡改或外部直接访问。
- 基本类型(int、boolean 等)用 final 即可保证值不可变
- 引用类型(如 List、Map、自定义对象)不仅要 final,还要确保其自身也不可变,或做防御性拷贝
不提供任何修改状态的方法
不可变对象不能有 setter、add、clear、sort 等任何会改变内部状态的方法。所有“看起来在修改”的操作(如 String 的 substring、toUpperCase),实际都返回一个新对象。
- 避免返回可变内部对象的引用(比如 getItems() 直接返回 private List<T>)
- 若需暴露集合,应返回 不可变视图(Collections.unmodifiableList)或防御性拷贝(new ArrayList(original))
构造过程确保状态安全
构造器是对象唯一一次设置内部状态的机会,必须严防“逸出”——即在构造完成前就把 this 引用泄露出去(例如注册监听、启动线程、传给静态方法)。
立即学习“Java免费学习笔记(深入)”;
- 构造器内不要调用可被子类重写的方法(可能访问未初始化字段)
- 若字段是可变对象(如 Date、StringBuilder),接收参数时做防御性拷贝,再存入 final 字段
- 示例:this.time = new Date(originalTime.getTime()); 而非 this.time = originalTime;
类本身声明为 final 或禁止继承
防止子类通过重写方法破坏不可变性(比如覆写 getter 返回可变副本,或添加 setter)。最稳妥方式是将类声明为 final;若必须支持继承,至少把所有方法设为 final,并严格审查子类扩展点。
- 不加 final 类 ≠ 不可变,只是增加了被破坏的风险
- Effective Java 第 17 条明确建议:为了不可变性,类应当是 final 的


















