反射比较两个对象属性名相同值不同

Posted 好大的月亮

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了反射比较两个对象属性名相同值不同相关的知识,希望对你有一定的参考价值。

概述

有时会遇到获取一个class下2个对象相同属性的不同值的属性。方便在页面上展示差异属性,标识个颜色啥的。

代码Demo

package xxx.xxx.xxx.xxx;


import com.xxx.xxx.xxx.ProductSkuBaseInfoVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ArrayUtils;

import java.beans.*;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;



@Slf4j
public class Util 

 

    public static void main(String[] args) 
        ProductSkuBaseInfoVO source = new ProductSkuBaseInfoVO();
        source.setCategoryId(111L);
        source.setDepartmentId(222L);


        ProductSkuBaseInfoVO target = new ProductSkuBaseInfoVO();
        target.setCategoryId(112L);
        target.setDepartmentId(322L);

        List<String> list = compareDiffField(source, target);
        System.out.println(list);


    


    public static List<String> compareDiffField(Object source, Object target, String... ignoreFiledNames)
        List<String> diffFieldNames = new ArrayList<>(20);

        if(Objects.isNull(source) || Objects.isNull(target))
            return diffFieldNames;
        

        Class<?> sourceClass = source.getClass();
        Class<?> targetClass = target.getClass();


        BeanInfo sourceBeanInfo = null;
        BeanInfo targetBeanInfo = null;
        try 
            //一段时间内可以重复使用,内部get时候的 beanInfoCache 是一个WeakHashMap,每次gc被回收
            sourceBeanInfo = Introspector.getBeanInfo(sourceClass);
            targetBeanInfo = Introspector.getBeanInfo(targetClass);
         catch (IntrospectionException e) 
            log.error("获取对象BeanInfo失败");
            return diffFieldNames;
        

        List<PropertyDescriptor> sourcePropertyDescriptors = Arrays.asList(sourceBeanInfo.getPropertyDescriptors());
        Map<String, PropertyDescriptor> targetPropertyDescriptorMap = Stream
                                                                        .of(targetBeanInfo.getPropertyDescriptors())
                                                                        .collect(
                                                                                Collectors.toMap(
                                                                                        FeatureDescriptor::getName,
                                                                                        it -> it,
                                                                                        (k1, k2) -> k2
                                                                                )
                                                                        );

        if(ArrayUtils.isNotEmpty(ignoreFiledNames))
            //忽略指定的属性的比较
            sourcePropertyDescriptors = sourcePropertyDescriptors
                    .stream()
                    .filter(it -> !ArrayUtils.contains(ignoreFiledNames, it.getName()))
                    .collect(Collectors.toList());
        


        for (PropertyDescriptor sourcePropertyDescriptor : sourcePropertyDescriptors) 

            String propertyName = sourcePropertyDescriptor.getName();
            PropertyDescriptor targetPropertyDescriptor = targetPropertyDescriptorMap.get(propertyName);

            if(Objects.isNull(targetPropertyDescriptor))
                //目标对象不存在此属性
                continue;
            

            Method sourceReadMethod = sourcePropertyDescriptor.getReadMethod();
            Method targetReadMethod = targetPropertyDescriptor.getReadMethod();

            if(Objects.isNull(sourceReadMethod) || Objects.isNull(targetReadMethod))
                //未找到get方法
                continue;
            

            try 
                Object sourceReadValue = sourceReadMethod.invoke(source);
                Object targetReadValue = targetReadMethod.invoke(target);

                if(!Objects.equals(sourceReadValue, targetReadValue))
                    //收集值有差异的属性name
                    diffFieldNames.add(propertyName);
                

             catch (IllegalAccessException | InvocationTargetException e) 
                log.error("比较获取不同属性方法出现异常,e:0", e);
            

        

        return diffFieldNames;
    



以上是关于反射比较两个对象属性名相同值不同的主要内容,如果未能解决你的问题,请参考以下文章

C#利用反射实现两个类的对象之间相同属性的值的复制

java使用反射比较两个bean对象属性值是否相等

C#通过反射实现两个对象相同属性值的复制

[反射]比较两个VO对象的值

对比两个对象的属性和值是否完全相同

java反射工具类--通过指定属性名,获取/设置对象属性值