setter中校验必须前置,先检查后赋值,禁止先赋值再校验;数值型查边界、字符串判空trim、格式用正则、枚举用集合检查;构造函数应调用setter而非直接赋值;强约束抛IllegalArgumentException,弱约束可设默认值。

在 setter 中拦截非法值,核心是把校验逻辑放在赋值动作之前,不满足条件就立即抛出运行时异常,阻止对象状态被污染。
校验必须前置,赋值必须后置
setter 的执行顺序直接影响数据安全性:
- ✅ 先检查:比如 if (age 150),再抛异常
- ✅ 后赋值:只有校验通过才执行 this.age = age;
- ❌ 绝不能先写 this.age = age;,再判断再 throw —— 此时非法值已写入,对象状态已破坏
常见类型校验写法示例
不同字段类型需对应不同校验重点:
- 数值型:检查边界,如 if (value 150) throw new IllegalArgumentException("年龄必须在 0~150 之间");
- 字符串型:先判空再 trim,如 if (email == null || email.trim().isEmpty()) throw new IllegalArgumentException("邮箱不能为空");
- 格式型:用正则匹配,如 if (!email.matches("^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$")) throw ...
- 枚举/固定值:用集合检查,如 if (!List.of("ACTIVE", "INACTIVE").contains(status)) throw ...
构造函数也要走 setter
避免绕过校验的典型错误:
- ❌ 构造函数里直接写 this.age = age; —— 跳过了所有校验逻辑
- ✅ 应统一调用 this.setAge(age); 或在构造函数中复用 setter 内部逻辑
- 这样能保证无论通过 new 还是后续 set 修改,校验都只维护一处,不易遗漏
异常类型与处理策略
根据业务强弱约束决定响应方式:
- 强约束字段(如 ID、必填邮箱、主键):推荐抛 IllegalArgumentException,让调用方明确感知错误
- 弱约束或容错场景(如用户输入负年龄):可设默认值,如 this.age = Math.max(0, value);,但需文档说明
- 不建议静默忽略或自动修正(如 trim 后赋值),除非业务明确要求且团队共识
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











