java不可变对象设计需通过final类与字段、防御性拷贝、安全getter及无修改接口三重机制实现:类和字段声明为final,可变参数构造时深拷贝,getter返回不可变视图或副本,所有操作返回新对象。

Java 封装时设计不可变对象,核心不是“藏数据”,而是通过访问控制 + 初始化约束 + 引用隔离三重机制,让对象从创建起就无法被外部改变状态。关键在于切断所有可能的修改路径,而不是依赖开发者自觉。
类和字段必须用 final 严防篡改
类声明为 final,避免子类覆盖方法或引入可变逻辑;所有字段必须是 private final,既不让外部读写,也不允许构造后重新赋值。
- 比如
private final String name;:String 本身不可变,字段又不可重指向,双重保险 - 若字段是数组或集合(如
private final List<string> tags;</string>),仅加 final 不够——它只锁住引用,不锁住内容
构造时做防御性拷贝,隔绝外部输入污染
只要参数是可变类型(Date、ArrayList、char[] 等),就不能直接赋值,必须在构造器里创建副本。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 传入
Date d→ 写成this.birthDate = new Date(d.getTime()); - 传入
List<string> emails</string>→ 先new ArrayList(emails),再包装成Collections.unmodifiableList(...) - 传入
char[] arr→ 用Arrays.copyOf(arr, arr.length),而非直接引用原数组
getter 方法必须返回安全副本,不暴露内部引用
对外提供访问时,不能返回原始可变对象的引用,否则调用方一改就破坏了内部状态。
- 返回
List字段?用Collections.unmodifiableList(内部副本) - 返回
byte[]或int[]?用Arrays.copyOf(...)或clone() - 返回
String或Integer?可直接返回——它们本就是不可变类型,无需额外处理
不提供任何修改接口,连“看起来像修改”的入口都关闭
不写 setXXX()、add()、clear() 等方法;所有“变换”操作(如 withName()、plusAge())都应返回一个新对象,原对象保持原样。
- 例如:
public Person withAge(int newAge) { return new Person(this.name, newAge, this.birthDate); } - 禁止在方法中修改
this的任何字段,哪怕只是临时计算也不行 - 连
toString()、hashCode()这类方法,也必须基于 final 字段纯计算,不缓存可变中间状态
不复杂但容易忽略
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










