不可变对象的完全封装要求构造即终局、访问即只读、类型即契约:私有构造器+全参数校验,getter不泄露可变引用,类与字段均final,辅以静态工厂和record简化实现。

在不可变对象设计中实现完全封装,关键不是“把字段设成 private”就完事,而是从对象生命周期的起点(创建)到终点(使用)全程切断外部对内部状态的任何干预可能。它要求构造即终局、访问即只读、类型即契约。
构造阶段彻底封闭:私有构造器 + 全参数校验
不可变对象必须在实例化时完成全部状态初始化,且不允许后续修改。因此构造逻辑不能暴露给外部:
- 声明 private 构造器,杜绝
new ImmutablePoint(1.0, 2.0)这类直接调用 - 所有字段校验(如坐标非 NaN、字符串非 null)必须在构造器内完成,失败即抛异常,不留下半成品对象
- 若需多种构建方式(如从字符串解析、从配置加载),统一收口到静态工厂方法中,例如
ImmutablePoint.of(x, y)或ImmutablePoint.parse("1.0,2.0")
访问接口严格只读:无 setter,getter 不泄露可变引用
getter 方法表面简单,但稍不注意就会破坏封装:
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
- 基本类型(
int,double)直接返回值,安全 - 引用类型(如
List<string></string>)不能返回内部字段原引用,否则调用方可通过list.add(...)修改状态;应返回Collections.unmodifiableList(...)或 Java 9+ 的List.copyOf(...) - 避免提供任何可能间接修改状态的方法,比如不暴露内部缓存 map 的 getter
类型系统强化契约:final 类 + final 字段 + record 可选
语法层面对抗意外继承和篡改:
- 类声明为 final,防止子类绕过封装重写方法或添加可变字段
- 所有字段声明为 private final,确保编译期与运行期都不可变
- Java 14+ 可考虑用 record 替代手工写的不可变类,它天然满足 final 类、final 字段、不可变语义,且自动生成构造器、getter 和
equals/hashCode
配合工厂模式隐藏创建细节
即使对象本身不可变,其创建过程仍可能涉及配置读取、依赖注入或格式转换。这些不该由调用方操心:
- 工厂类(如
ImmutableConfigFactory)负责解析 YAML、校验必填项、设置默认值 - 工厂返回的是接口或 record 类型,而非具体实现类名,调用方连“它是不是不可变”都不需要知道
- 若未来需支持热重载配置,工厂内部可切换为带版本号的不可变快照,调用方代码零改动
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










