java属性封装中,setter必须统一校验数据:构造函数也应调用setter;强约束字段抛illegalargumentexception,弱约束可自动修正;校验逻辑需独立纯净可测;可变对象需防御性拷贝避免假封装。

Java 属性封装中,利用 setter 方法校验数据是保障对象状态合法性的核心手段。关键不是“加了 setter”,而是让 setter 真正承担起拦截、判断和控制的责任。
校验必须写在 setter 里,不能绕过
setter 是唯一可靠的赋值入口。如果构造函数或别的方法直接给 private 字段赋值(比如 this._age = age;),就等于拆掉了校验防线。
- ✅ 正确做法:构造函数里也调用 this.setAge(age),让校验逻辑统一执行
- ❌ 错误做法:在构造器中跳过 setter,直接写 this.age = age;外部传入非法值时毫无察觉
校验要明确失败处理方式
不是所有非法输入都该抛异常——得看业务语义。
- 强约束字段(如用户 ID、订单号):值不合法就抛 IllegalArgumentException,阻止对象进入不一致状态
- 弱约束字段(如年龄、昵称):可自动修正,比如负数年龄设为 0,空字符串昵称设为 "匿名"
- 避免静默失败:既不报错也不修正,会让 bug 潜伏到后续逻辑中才暴露
校验逻辑要独立、纯净、可测
复杂判断别堆在 setter 体内,应抽成私有方法,但必须满足两个条件:
- 只依赖传入参数,不读取 this 的其他字段(比如不查 this.config 或调用 this.isValid())
- 不触发副作用(不发 HTTP 请求、不改数据库、不打日志)
- 例如:private boolean isValidEmail(String email) 可复用、易单元测试;而 private void sendVerificationEmail() 就不该塞进 setter
注意可变对象的“假封装”陷阱
即使 age 字段校验严格,如果有个 private List
- 正确返回方式:return Collections.unmodifiableList(new ArrayList(this.tags));
- 更安全的做法:只提供 addTag(String tag) 和 getTagsCopy(),彻底封死原始引用暴露
- String、LocalDateTime 这类不可变类型可以放心 public final,但 List、Map、数组不行
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











