Files
2026-05-17 09:32:34 +08:00

5.7 KiB
Raw Permalink Blame History

我的公众号

Java_ConstractUtil

通用的Java同类型对象对比工具类,用于比较两个同类型对象的属性差异,并返回变化的部分。


快速开始

Maven依赖

<dependency>
    <groupId>Java_ConstractUtil</groupId>
    <artifactId>Java_ConstractUtil</artifactId>
    <version>1.0.0</version>
</dependency>

基本使用

// 比较两个同类型对象
SimpleObj origin = new SimpleObj();
origin.setX(1);
origin.setY("hello");

SimpleObj target = new SimpleObj();
target.setX(2);
target.setY("hello");

ContrastObject<SimpleObj> result = ContrastUtil.contrast(origin, target);
if (result != null) {
    // result.getOriginChange()  -> 原始对象中发生变化的属性 (x=1)
    // result.getTargetChange()  -> 修改后对象中发生变化的属性 (x=2)
    System.out.println(result.getOriginChange().getX()); // 1
    System.out.println(result.getTargetChange().getX()); // 2
}

工具说明

ContrastUtil(通用对比工具)

ContrastUtil 是默认的对象对比实现类,提供静态方法 contrast(T origin, T target) 进行对象对比。

处理规则:

  1. 基本类型和包装类型:直接使用 equals 进行比较(如 intStringDate 等)
  2. Collection类型:比较两个集合的差异,返回差集。仅处理一层,泛型内的元素直接调用 equals 比较
  3. Map类型:比较两个Map的差异,包括相同key的value比较和不同key的差异
  4. 自定义类型:调用 equals 方法进行比较,要求重写 equalshashCode 方法,否则会比较对象地址
  5. 类型一致性:比较的两个对象类型必须一致,否则抛出 TypeMisMatchException
  6. 空值处理:入参可以为 null,两者都为 null 返回 null,其中一个为 null 则返回非空一方的结果
  7. Getter/Setter检查:自定义类型必须有完整的 get/set 方法,否则抛出 NoGetMethodException / NoSetMethodException
  8. 抽象类和接口:不支持抽象类和接口的实例对比,会直接返回 null

返回值说明:

ContrastObject<T> 包含四个字段:

  • origin:原始对象(完整)
  • target:修改后的对象(完整)
  • originChange:原始对象中发生变化的属性(新实例,仅包含变化的字段)
  • targetChange:修改后对象中发生变化的属性(新实例,仅包含变化的字段)

无变化时返回 null


AbstractContrastUtil(抽象基类)

AbstractContrastUtil<T> 提供最大的自定义性,使用者可以通过继承并实现抽象方法来定制各种类型的对比逻辑。

需要实现的抽象方法:

方法 说明
originContract() 基本类型和包装类型的对比逻辑
selfContract() 自定义类型的对比逻辑
mapContract() Map类型的对比逻辑
collectionContract() Collection类型的对比逻辑
specialContract() 特殊类型的自定义处理逻辑
isSpecialType() 判断是否为特殊类型(优先于Collection/Map判断)
nullProcessor() 入参为null的处理逻辑
originProcessor() 基本类型入参的处理逻辑
setContrastObject() 组装返回结果对象

使用示例: 参考 ContrastUtilExample.java


项目结构

src/main/java/
├── ContrastUtil.java              # 默认对比工具实现
├── AbstractContrastUtil.java      # 抽象对比基类
├── ContrastUtilExample.java       # 抽象基类使用示例
├── bean/
│   └── ContrastObject.java        # 对比结果包装类
├── constant/
│   └── Constant.java              # 常量定义
├── exception/
│   ├── NoGetMethodException.java  # 缺少getter方法异常
│   ├── NoSetMethodException.java  # 缺少setter方法异常
│   └── TypeMisMatchException.java # 类型不匹配异常
├── handler/
│   ├── CollectionHandler.java     # Collection类型处理器
│   ├── MapHandler.java            # Map类型处理器
│   ├── OriginHandler.java         # 基本类型处理器
│   └── SelfHandler.java           # 自定义类型处理器
└── util/
    ├── CheckUtil.java             # 类型检查工具
    ├── ClassUtil.java             # 类反射工具
    ├── CollectionUtil.java        # 集合差异计算工具
    ├── MapUtil.java               # Map工具
    └── SetUtil.java               # Set工具

依赖

依赖 版本 用途
commons-lang3 3.9 通用工具
commons-collections4 4.4 集合工具
guava 28.2-jre Google工具库
reflectasm 1.11.0 高性能反射

注意事项

  1. Collection和Map仅处理一层,嵌套的泛型类型直接调用 equals 比较,可能导致结果不准确。如需深度对比,请使用 AbstractContrastUtil 自定义处理逻辑
  2. 自定义类型必须重写 equalshashCode 方法,否则会比较对象地址而非值
  3. 当前使用 reflectASM 进行反射调用,性能优于标准反射,但仍有优化空间
  4. 暂不支持 is 前缀的 boolean getter 方法(如 isActive()),后续版本会支持

更新日志

  • 2020/4/30:创建项目,完成初始实现和单元测试
  • 2020/5/9:添加测试方法,修复反射处理null的空指针问题,创建抽象类和继承使用示例
  • 2026/5/17:修复多个bugMapHandler参数错误、OriginHandler空值比较逻辑、ContrastObject NPE风险等),优化代码实现,补全注释和文档