Java比较两个对象是否相同并获取值不同的属性

简介: Java比较两个对象是否相同并获取值不同的属性

最新项目中要加操作日志,同时要把用户修改了那些字段记录下来,在更新的时候就需要比较之前的数据和现在的数据有哪些不同,这么多类一个一个的比较就太麻烦了,所以打算写一个工具类。

主要思想还是通过反射获取类的属性的getter方法,调用getter方法获取值并比较是否相同,相同就忽略不同就返回属性信息,方法都不复杂,主要是利用反射思想。


代码如下:

定义一个类保存比较后的返回值信息

@Data
public class PropertyModelInfo {
    //属性名
    private String propertyName;
    // 属性值
    private Object value;
    // 返回值类型
    private Class<?> returnType;
}

修改后的属性信息:

public class ModifiedPropertyInfo implements Serializable {
    // 对应的属性名
    private String propertyName;
    // 未修改之前的值
    private Object oldValue;
    // 修改后的值
    private Object newValue;
}

逻辑代码:

/**
     *  比较两个对象属性值是否相同
     *  如果不同返回修改过的属性信息
     * @param oldObj
     * @param newObj
     * @param ignoreProperties
     * @param <T>
     * @return 修改过的属性字段
     */
    public static <T> List<ModifiedPropertyInfo> getDifferentProperty(T oldObj , T newObj , String... ignoreProperties){
        if (oldObj != null && newObj != null) {
            // 比较全部字段
            if (ignoreProperties == null || ignoreProperties.length > 0) {
                if (oldObj.equals(newObj)) {
                    return Collections.emptyList();
                }
            }
            List<PropertyModelInfo> oldObjectPropertyValue = getObjectPropertyValue(oldObj, ignoreProperties);
            if (!CollectionUtils.isEmpty(oldObjectPropertyValue)) {
                List<ModifiedPropertyInfo> modifiedPropertyInfos = new ArrayList<>(oldObjectPropertyValue.size());
                List<PropertyModelInfo> newObjectPropertyValue = getObjectPropertyValue(newObj, ignoreProperties);
                Map<String , Object> objectMap = new HashMap<>(newObjectPropertyValue.size());
                // 获取新对象所有属性值
                for (PropertyModelInfo propertyModelInfo : newObjectPropertyValue) {
                    String propertyName = propertyModelInfo.getPropertyName();
                    Object value = propertyModelInfo.getValue();
                    objectMap.put(propertyName , value);
                }
                for (PropertyModelInfo propertyModelInfo : oldObjectPropertyValue) {
                    String propertyName = propertyModelInfo.getPropertyName();
                    Object value = propertyModelInfo.getValue();
                    if (objectMap.containsKey(propertyName)) {
                        Object newValue = objectMap.get(propertyName);
                        ModifiedPropertyInfo modifiedPropertyInfo = new ModifiedPropertyInfo();
                        if (value != null && newValue != null) {
                            // 是否相等
                            boolean equal = false;
                            if (value instanceof BigDecimal) {
                                // BigDecimal 用 equal  比较
                                if (((BigDecimal) value).compareTo((BigDecimal) newValue) != 0) {
                                    equal = true;
                                }
                            }else if (!value.equals(newValue)) {
                                equal = true;
                            }
                            if (equal) {
                                modifiedPropertyInfo.setProperty(propertyName);
                                modifiedPropertyInfo.setOldValue(value);
                                modifiedPropertyInfo.setNewValue(newValue);
                                modifiedPropertyInfos.add(modifiedPropertyInfo);
                            }
                        }else if (value != null || newValue != null){
                            modifiedPropertyInfo.setProperty(propertyName);
                            modifiedPropertyInfo.setOldValue(value);
                            modifiedPropertyInfo.setNewValue(newValue);
                            modifiedPropertyInfos.add(modifiedPropertyInfo);
                        }
                    }
                }
                return modifiedPropertyInfos;
            }
        }
        return Collections.emptyList();
    }
 /**
     *  通过反射获取对象的属性名称、getter返回值类型、属性值等信息
     * @param obj
     * @param ignoreProperties
     * @param <T>
     * @return
     */
    public static  <T> List<PropertyModelInfo> getObjectPropertyValue(T obj , String... ignoreProperties){
        if (obj != null) {
            Class<?> objClass = obj.getClass();
            PropertyDescriptor[] propertyDescriptors = BeanUtils.getPropertyDescriptors(objClass);
            List<PropertyModelInfo> modelInfos = new ArrayList<>(propertyDescriptors.length);
            List<String> ignoreList = (ignoreProperties != null ? Arrays.asList(ignoreProperties) : null);
            for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
                Method readMethod = propertyDescriptor.getReadMethod();
                String name = propertyDescriptor.getName();
                if (readMethod != null && (ignoreList == null || !ignoreList.contains(name))) {
                    Object invoke = null;
                    Class<?> returnType = readMethod.getReturnType();
                    try {
                        invoke = readMethod.invoke(obj);
                        PropertyModelInfo propertyModelInfo = new PropertyModelInfo();
                        propertyModelInfo.setPropertyName(name);
                        propertyModelInfo.setValue(invoke);
                        propertyModelInfo.setReturnType(returnType);
                        modelInfos.add(propertyModelInfo);
                    } catch (IllegalAccessException | InvocationTargetException e) {
                        LOGGER.error("反射获取类【"+objClass.getName()+"】方法异常," , e);
                    }
                }
            }
            return modelInfos;
        }
        return Collections.emptyList();
    }

测试:

  HouseInfo houseInfo = new HouseInfo();
        houseInfo.setAddress("test1");
        HouseInfo houseInfo2 = new HouseInfo();
        houseInfo2.setAddress("test2");
        //改变值
        List<ModifiedPropertyInfo> modifiedPropertyInfos = ReflectUtil.getDifferentProperty(houseInfo, houseInfo2);
        System.out.println(modifiedPropertyInfos);
        // 不改变值
        houseInfo2.setAddress("test1");
        modifiedPropertyInfos = ReflectUtil.getDifferentProperty(houseInfo, houseInfo2);
        System.out.println(modifiedPropertyInfos);

结果:

[ModifiedPropertyInfo(propertyName=address, oldValue=test1, newValue=test2)]
[]

步骤:

1、获取对象的属性属性值

2、跟另一个对象的所有属性值比较


能力一般,水平有限,如有错误,请多指出

目录
相关文章
|
10天前
|
存储 Java
java的对象详解
在Java中,对象是根据类模板实例化的内存实体,具有唯一标识符、属性及行为。通过`new`关键字实例化对象并用构造方法初始化。变量存储的是对象引用而非对象本身,属性描述对象状态,方法定义其行为。Java利用垃圾回收机制自动处理不再使用的对象内存回收,极大地简化了对象生命周期管理,同时对象具备封装、继承和多态性,促进了代码的重用与模块化设计。这使得Java程序更易于理解、维护和扩展。
|
6天前
|
Java 编译器
Java——类与对象(继承和多态)
本文介绍了面向对象编程中的继承概念,包括如何避免重复代码、构造方法的调用规则、成员变量的访问以及权限修饰符的使用。文中详细解释了继承与组合的区别,并探讨了多态的概念,包括向上转型、向下转型和方法的重写。此外,还讨论了静态绑定和动态绑定的区别,以及多态带来的优势和弊端。
20 9
Java——类与对象(继承和多态)
|
6天前
|
SQL Java 编译器
Java——类与对象(封装)
封装是面向对象编程中的概念,指将数据(属性)和相关操作(方法)组合成独立单元(类),使外部无法直接访问对象的内部状态,只能通过提供的方法进行交互,从而保护数据安全。例如,手机将各种组件封装起来,只暴露必要的接口供外部使用。实现封装时,使用`private`关键字修饰成员变量,并提供`get`和`set`方法进行访问和修改。此外,介绍了包的概念、导入包的方式及其注意事项,以及`static`关键字的使用,包括静态变量和方法的初始化与代码块的加载顺序。
18 10
Java——类与对象(封装)
|
6天前
|
Java C语言
Java——类与对象
这段内容介绍了Java中的类和对象、`this`关键字及构造方法的基本概念。类是对现实世界事物的抽象描述,包含属性和方法;对象是类的实例,通过`new`关键字创建。`this`关键字用于区分成员变量和局部变量,构造方法用于初始化对象。此外,还介绍了标准JavaBean的要求和生成方法。
18 9
Java——类与对象
|
7天前
|
存储 Java
Java的对象和类的相同之处和不同之处
在 Java 中,对象和类是面向对象编程的核心。
|
7天前
|
存储 Java
Java编程中的对象序列化与反序列化
【9月更文挑战第12天】在Java的世界里,对象序列化与反序列化是数据持久化和网络传输的关键技术。本文将带你了解如何通过实现Serializable接口来标记一个类的对象可以被序列化,并探索ObjectOutputStream和ObjectInputStream类的使用,以实现对象的写入和读取。我们还将讨论序列化过程中可能遇到的问题及其解决方案,确保你能够高效、安全地处理对象序列化。
|
9天前
|
Java 编译器 测试技术
|
12天前
|
Java
Java 对象和类
在Java中,**类**(Class)和**对象**(Object)是面向对象编程的基础。类是创建对象的模板,定义了属性和方法;对象是类的实例,通过`new`关键字创建,具有类定义的属性和行为。例如,`Animal`类定义了`name`和`age`属性及`eat()`、`sleep()`方法;通过`new Animal()`创建的`myAnimal`对象即可调用这些方法。面向对象编程通过类和对象模拟现实世界的实体及其关系,实现问题的结构化解决。
|
15天前
|
存储 Java 程序员
优化Java多线程应用:是创建Thread对象直接调用start()方法?还是用个变量调用?
这篇文章探讨了Java中两种创建和启动线程的方法,并分析了它们的区别。作者建议直接调用 `Thread` 对象的 `start()` 方法,而非保持强引用,以避免内存泄漏、简化线程生命周期管理,并减少不必要的线程控制。文章详细解释了这种方法在使用 `ThreadLocal` 时的优势,并提供了代码示例。作者洛小豆,文章来源于稀土掘金。
|
9天前
|
Java 程序员
Java编程中的对象和类: 初学者指南
【9月更文挑战第9天】在Java的世界中,对象和类构成了编程的基石。本文将引导你理解这两个概念的本质,并展示如何通过它们来构建你的程序。我们将一起探索类的定义,对象的创建,以及它们如何互动。准备好了吗?让我们开始这段Java的旅程吧!