Java中复用校验逻辑应优先采用模板方法模式+泛型抽象基类,封装通用检查与错误收集,避免构造器校验;强业务耦合场景可用继承,但通用规则更推荐Jakarta注解+自定义约束器。

Java 中通过继承复用通用校验逻辑,核心思路是把校验规则抽象到父类中,子类继承后可直接调用或按需扩展。关键不在于“能不能继承”,而在于“怎么设计才不破坏封装、不导致耦合过重”。
把校验方法声明为 protected 或模板方法
父类中定义通用校验逻辑,用 protected 修饰,确保子类可访问但外部不可调用;更推荐使用模板方法模式,把流程骨架固定,具体规则由子类实现:
- 父类定义
validate()公共方法,内部调用doValidate()(抽象或默认空实现) - 子类重写
doValidate(),只关注自身业务字段的校验,如非空、范围、格式等 - 父类还可内置通用检查(如 ID 是否为正数、时间是否为过去时),统一执行
用泛型 + 抽象基类统一入参和错误收集
避免每个子类自己 new ArrayList<String> 收集错误。父类可定义泛型参数,并持有一个 List<String> 错误列表:
Java开发手册规约集合,基于阿里巴巴Java开发手册(嵩山版)。 涵盖7大维度:编程规约、异常日志、单元测试、安全规约、MySQL数据库、工程结构、设计规约。 当用户需要:(1) 编写或审查Java代码 (2) 检查命名/代码规范 (3) 处理异常和日志 (4) 编写单元测试 (5) 安全编码 (6) 数据库设...
- 父类提供
addError(String msg)和hasErrors()方法 - 子类校验失败时调用
addError("用户名不能为空"),无需关心存储细节 - 最终统一返回
Map<String, List<String>>或自定义ValidationResult对象
避免在构造函数里做校验,优先用独立 validate() 方法
继承场景下,子类构造器可能早于父类校验逻辑执行,容易出错或绕过检查。更稳妥的做法是:
立即学习“Java免费学习笔记(深入)”;
- 对象创建后显式调用
validate()(如 Service 层接收 DTO 后先校验再处理) - 若必须构建即校验,可在父类构造器末尾调用
validate(),但要求子类构造器必须先完成字段赋值 - 不建议在父类构造器中调用可被重写的非 final 方法(存在 this 引用逸出风险)
配合注解校验(如 Jakarta Bean Validation)更轻量且解耦
纯继承方式适合强业务耦合、规则高度相似的场景;但多数通用校验(非空、长度、邮箱格式等)更适合用标准注解:
- 在 DTO 上加
@NotBlank、@Min(1)等,用Validator.validate()统一触发 - 自定义注解(如
@ValidPhone)+ ConstraintValidator 实现复用,比继承更灵活 - 继承可与注解结合:父类 DTO 定义公共字段及其注解,子类继承并添加自有字段注解

















