java不可变对象需私有final字段、无setter、构造器全初始化、防御性拷贝可变组件、类声明final,并杜绝可变引用暴露。

Java中不可变对象通过封装实现,核心是禁止外部修改内部状态,同时确保对象创建后状态恒定。这不单靠private修饰,而是一整套设计约束。
私有化所有字段并移除setter方法
字段必须声明为private,且不提供任何public setter方法。这是封装的第一步,切断外部直接写入的通道。
- 所有实例变量用private final修饰,既限制访问又保证初始化后不可重赋值
- 避免提供类似
setName(String name)这类修改内部状态的方法 - 构造器是唯一允许初始化字段的地方,且应完成全部状态赋值
防御性拷贝(Defensive Copy)保护可变组件
如果类包含可变对象(如Date、ArrayList、数组等),直接返回引用会破坏不可变性。必须在getter中返回副本。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 对数组:用
Arrays.copyOf()或clone()返回新数组 - 对集合:用
new ArrayList(originalList)或unmodifiableList()包装(注意后者仅防修改,不防原始引用泄露) - 对可变对象(如java.util.Date):在getter中新建实例,例如
return new Date(this.date.getTime())
确保子类无法破坏不可变性
若类可能被继承,子类可通过重写方法或添加可变字段绕过约束。最稳妥方式是将类声明为final。
- 声明
public final class Person { ... },杜绝继承带来的风险 - 若必须支持继承,至少将所有方法设为final,但不如类final来得彻底
- 避免在构造器中调用可被重写的方法(防止this逃逸和子类干预初始化)
不提供可变的内部视图或回调入口
即使字段私有,若通过返回可变对象引用、注册监听器、或暴露Builder/Fluent接口,仍可能间接修改状态。
- 禁止在getter中返回内部可变对象的原始引用
- 不提供类似
asMap()返回内部HashMap的接口(除非返回Collections.unmodifiableMap) - 避免在构造时接受回调函数并存储其引用,以防回调内修改本对象或其依赖
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










