Java字段比较工具类设计

        以下是一个设计用于比较两个同类型对象字段变化的工具类,它使用Java反射机制检查每个字段是否有变化(不考虑递归深度比较):

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

public class FieldChangeComparator {

    /**
     * 比较两个同类型对象的所有字段是否有变化
     * @param obj1 第一个对象
     * @param obj2 第二个对象
     * @param <T>  对象类型
     * @return Map键为字段名,值为是否变化(true=有变化)
     * @throws IllegalArgumentException 对象类型不同或均为null时抛出
     */
    public static <T> Map<String, Boolean> compareFields(T obj1, T obj2) {
        // 验证对象有效性
        if (obj1 == null && obj2 == null) {
            throw new IllegalArgumentException("Both objects cannot be null");
        } else if (obj1 == null || obj2 == null) {
            throw new IllegalArgumentException("One object is null while the other is not");
        }
        
        Class<?> clazz = obj1.getClass();
        if (!clazz.equals(obj2.getClass())) {
            throw new IllegalArgumentException("Objects must be of the same type");
        }

        Map<String, Boolean> result = new HashMap<>();
        Field[] fields = clazz.getDeclaredFields();
        
        for (Field field : fields) {
            field.setAccessible(true);  // 允许访问私有字段
            try {
                Object value1 = field.get(obj1);
                Object value2 = field.get(obj2);
                
                // 使用Objects.equals进行空安全比较
                boolean changed = !Objects.equals(value1, value2);
                result.put(field.getName(), changed);
                
            } catch (IllegalAccessException e) {
                // 处理访问异常(通常不会发生,因为已setAccessible)
                System.err.println("Error accessing field: " + field.getName());
                result.put(field.getName(), true);  // 按有变化处理
            }
        }
        return result;
    }
}

使用示例:

public class Person {
    private String name;
    private int age;
    private Address address;  // 自定义引用类型

    // 构造方法/getters/setters省略
}

// 测试比较
Person p1 = new Person("Alice", 30, new Address("Paris"));
Person p2 = new Person("Alice", 31, new Address("Paris"));

Map<String, Boolean> changes = FieldChangeComparator.compareFields(p1, p2);

// 输出结果示例:
// name -> false (未变化)
// age -> true  (变化)
// address -> false (注意:比较的是引用地址,非内容)

设计说明:

此实现满足快速检测字段级变更的需求,且避免了深度递归带来的复杂性。

  1. 功能特性

    • 比较同类型对象的所有字段(包括私有字段)

    • 返回字段名与变化状态的映射

    • 空安全比较(使用Objects.equals()

    • 自动处理基本类型和包装类型

  2. 关键逻辑

    !Objects.equals(value1, value2)

    等价于:

    • value1 == value2(包括都为null的情况)

    • value1.equals(value2)(当两者非null时)

  3. 注意事项

    • 引用类型比较:直接比较对象引用(不递归比较内部字段)

    • 静态字段:不比较静态字段(getDeclaredFields()不包含静态字段)

    • 异常处理

      • 类型不同或空对象会抛出IllegalArgumentException

      • 字段访问异常视为有变化(实际极少发生)

  4. 性能考虑

    • 适合中小型对象(反射操作有一定开销)

    • 对性能敏感场景建议缓存Field数组

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值