java可通过反射遍历对象字段比较值变化并生成变更日志:获取非static/transient字段并设为可访问,用objects.equals安全比较值,支持数组、集合及嵌套对象递归对比,格式化输出差异如“字段名: [旧值] → [新值]”,并可配置忽略字段与脱敏规则。

Java中可以通过反射遍历对象的字段,逐个比较值是否发生变化,并生成可读的变更日志。核心在于获取两个对象的相同字段、忽略静态/瞬态字段、处理基本类型与引用类型的差异、支持嵌套对象(可选)以及格式化输出。
获取并遍历所有可比字段
使用 Class.getDeclaredFields() 获取本类所有字段(含私有),过滤掉 static 和 transient 字段,再设为 accessible = true 以便读取私有值:
- 用
field.setAccessible(true)绕过访问控制 - 跳过
Modifier.isStatic(field.getModifiers())或Modifier.isTransient(...)的字段 - 建议按字段名排序(如
Arrays.sort(fields, Comparator.comparing(Field::getName))),让日志更稳定可读
安全读取字段值并处理类型差异
对每个字段,分别从 oldObj 和 newObj 中读取值,注意空值、包装类型与基本类型的统一比较:
- 用
field.get(obj)获取值;若为 null,直接参与比较(Objects.equals(a, b)可安全处理) - 避免用
==比较对象,一律用Objects.equals(val1, val2) - 对数组字段,用
Arrays.deepEquals();对集合/Map,Objects.equals已足够(前提是元素本身支持合理 equals) - 若字段是自定义类型且需深度对比,可递归调用同一比较逻辑(需加递归深度限制或循环引用检测)
构建结构化变更日志
只记录发生变化的字段,按需组织成文本或对象形式。例如输出为字符串列表:
- 格式建议:
"字段名: [旧值] → [新值]",值用String.valueOf()转换,避免toString()空指针 - 对敏感字段(如密码),可配置白名单/黑名单,跳过打印或脱敏(如替换为
"***") - 支持输出 JSON 或 Map 形式,便于集成审计日志系统
- 示例输出:
"username: john → jack", "status: ACTIVE → INACTIVE"
封装为通用工具方法
写一个静态工具方法,接收 oldObj、newObj 和可选配置(如忽略字段列表、脱敏规则),返回变更列表:
- 方法签名示例:
public static List<string> diff(Object oldObj, Object newObj, Set<string> ignoreFields)</string></string> - 内部用
LinkedHashMap<string pair>></string>先收集所有差异,再格式化,便于后续扩展(如返回字段名+旧值+新值三元组) - 可配合 Lombok 的
@Data或 Jackson 的@JsonIgnore注解做字段级控制(需额外解析注解)
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











