通过Java反射机制获取对象差异工具类
Java反射机制获取对象差异工具类
今天遇到一个需求,需要记录一下操作数据的动作,于是想到了可以使用java的反射来实现
工具类实现
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
/**
* 字段差异对比工具类
*/
public class ReflectionDiffUtil {
/**
* 获取对象差异集合
* @param oldObj 旧对象
* @param newObj 新对象
* @return 差异集合
*/
public static List<FieldDiff> getDiffList(Object oldObj, Object newObj) {
List<FieldDiff> diffList = new ArrayList<>();
if (oldObj == null || newObj == null) {
throw new IllegalArgumentException("对比对象不能为空");
}
if (!oldObj.getClass().equals(newObj.getClass())) {
throw new IllegalArgumentException("对比对象类型不一致");
}
Class<?> clazz = oldObj.getClass();
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
try {
field.setAccessible(true);
Object oldValue = field.get(oldObj);
Object newValue = field.get(newObj);
if (!Objects.equals(oldValue, newValue)) {
String fieldName = getFieldChineseName(field);
diffList.add(new FieldDiff(
fieldName,
oldValue,
newValue
));
}
} catch (IllegalAccessException e) {
throw new RuntimeException("字段访问失败: " + field.getName(), e);
}
}
return diffList;
}
/**
* 获取字段中文名称
*/
private static String getFieldChineseName(Field field) {
if (field.isAnnotationPresent(FieldName.class)) {
FieldName annotation = field.getAnnotation(FieldName.class);
return annotation.value();
}
return field.getName(); // 没有注解时返回字段名
}
/**
* 字段差异信息类
*/
public static class FieldDiff {
private String fieldName; // 中文字段名
private Object oldValue; // 旧值
private Object newValue; // 新值
public FieldDiff(String fieldName, Object oldValue, Object newValue) {
this.fieldName = fieldName;
this.oldValue = oldValue;
this.newValue = newValue;
}
// Getter方法省略...
}
/**
* 字段中文名注解
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface FieldName {
String value();
}
}
使用示例
1. 定义实体类
public class User {
@ReflectionDiffUtil.FieldName("用户ID")
private Long id;
@ReflectionDiffUtil.FieldName("用户姓名")
private String name;
@ReflectionDiffUtil.FieldName("用户年龄")
private Integer age;
// 构造方法/getter/setter省略...
}
2. 创建新旧对象
User oldUser = new User();
oldUser.setId(1L);
oldUser.setName("张三");
oldUser.setAge(25);
User newUser = new User();
newUser.setId(1L);
newUser.setName("李四");
newUser.setAge(30);
3. 获取差异列表
List<ReflectionDiffUtil.FieldDiff> diffs =
ReflectionDiffUtil.getDiffList(oldUser, newUser);
4. 输出结果
[用户姓名] 旧值:张三 → 新值:李四
[用户年龄] 旧值:25 → 新值:30
实现说明
-
注解定义
@FieldName注解用于标记字段的中文名称- 支持在运行时通过反射读取注解信息
-
核心方法
getDiffList()方法使用反射遍历所有字段- 通过
Objects.equals()安全比较字段值 - 自动跳过值相同的字段
-
异常处理
- 检查对象类型一致性
- 处理字段访问异常
- 空对象校验
扩展建议
1. 忽略字段
@FieldName(value = "创建时间", ignore = true)
private Date createTime;
2. 深度对比
if (field.getType().isPrimitive()) {
// 基础类型直接比较
} else {
// 递归调用 getDiffList()
}
3. 自定义比较器
public interface FieldComparator {
boolean compare(Object oldVal, Object newVal);
}

浙公网安备 33010602011771号