假如一个类只有几个字段,可以一个一个去比较判断,如果这个类有几十个甚至一百多个字段显然不能一个一个去比较,这里使用 java反射 和自定义注解去完成这个需求。
一、自定义注解
自定义一个注解,需要进行对比的字段属性,我们打上在字段上方打上该注解,name 则为字段的中文说明
import java.lang.annotation.*;
/**
* 字段注解,写上字段注释
*
* @author ChenHao
* @version 1.0.0
* Created at 2021/3/23 15:41
*/
@Documented
@Target({ElementType.FIELD}) //注解应用类型
@Retention(RetentionPolicy.RUNTIME) // 注解的类型
public @interface FieldName {
String name() default "";
}
二、在类属性上打上自定义注解
在需要进行属性比较的字段上打上自定义注解,请完善 get set 方法
public class Person {
@FieldName(name = "姓名")
private String name;
private String age;
@FieldName(name = "地址")
private String add;
// get set
}
三、解析注解
这里使用反射,获取到 这个类的所有字段,然后对比打上了自定义注解的字段,将两个字段的差别,以 姓名: 张三 -> 李四, 这样的形式 返回字符串,这里的操作可以任意按照需求修改。
可以选择对比 空字符串 "" 和 Null ,也可以忽略
import java.lang.reflect.Field;
/**
* 对象比较
*
* @author ChenHao
* @version 1.0.0
* Created at 2021/3/23 9:27
*/
public class ObjectCompare {
/**
* 功能描述: 对比两个对象,返回两个对象的差异
* 需要结合 FieldName 注解使用
* 注意 object 返回的 空字符串 和空
*
* @param o1 new
* @param o2 old
* @param emptyIgnore 是否 忽略 null 和空字符串的 比较
* @author: ChenHao
* Created at 2021/3/23 9:29
*/
public static String compareObject(Object o1, Object o2, boolean emptyIgnore) throws IllegalAccessException {
Field[] fields = o1.getClass().getDeclaredFields();
StringBuilder sb = new StringBuilder();
for (Field field : fields) {
field.setAccessible(true);
if ((field.get(o1) == null && field.get(o2) == null)
|| (emptyIgnore && (field.get(o1) == null && "".equals(field.get(o2))) || ("".equals(field.get(o1)) && field.get(o2) == null))) {
continue;
}
if ((field.get(o1) == null && field.get(o2) != null)
|| (field.get(o1) != null && field.get(o2) == null)
|| (!field.get(o1).equals(field.get(o2)))) {
FieldName annotation = field.getAnnotation(FieldName.class);
if (annotation != null) {
sb.append(annotation.name()).append(": ")
.append(field.get(o2)).append(" -> ")
.append(field.get(o1)).append("; ");
}
}
}
return sb.toString();
}
}
四、方法调用
只需要获取到 new 对象 和 old 对象,然后 ObjectCompare.compareObject(new, old, true);
即可获得 差别数据