Java比较两个对象中属性值是否相同【使用反射实现】

  • 作者: 凯哥Java(公众号:凯哥Java)
  • 工作小总结
  • 时间:2022-03-06 22:50
  • 2336人已阅读
简介 在工作中,有些场景下,我们需要对比两个完全一样对象的属性值是否相等。比如接口替换的时候,需要比较新老接口在相同情况下返回的数据是否

🔔🔔好消息!好消息!🔔🔔

 如果您需要注册ChatGPT,想要升级ChatGPT4。凯哥可以代注册ChatGPT账号代升级ChatGPT4

有需要的朋友👉:微信号 kaigejava2022

在工作中,有些场景下,我们需要对比两个完全一样对象的属性值是否相等。比如接口替换的时候,需要比较新老接口在相同情况下返回的数据是否相同。这个时候,我们怎么处理呢?这里凯哥就使用Java的反射类实现。

/**
 * 字段比较
 * @param vo1       主项
 * @param vo2       比较项
 */
private void compareFiledValue(DownTempMsg vo1, DownTempMsg vo2) {
    //需要比较的字段
    String [] filedArr = new String [] {"title","subTitle","dataMsg","remark","tempType","pline","bookIds","bookNames","downRemark","articleEndRemark","imgRemark",
            "videoUrl","imgUrl","extend","showDownType","downTypeStyle","headerDownText","footerDownText",
            "headerDownStyle","contentDownType","authorArr","pseudonym","introductionParagraphExtend","downGuideExtend","tempPercentage"};
    String strClazzName = "class java.lang.String";
    if(null != vo2){
        for(String filed:filedArr){
            if("imgCdnUrl".equals(filed)){
                log.info("123");
            }
            Object  obj1 = PropertyReflectUtil.getProperty(vo1,filed);
            Object  obj2 = PropertyReflectUtil.getProperty(vo2,filed);
            if(null != obj1 && null != obj2){
                String fieldType = PropertyReflectUtil.getPropertyType(vo1,filed);
                log.info("filed:{},fieldType:{}",filed,fieldType);
                //比较不同
                String obj1Md5 = "";
                String obj2Md5 = "";
                try {
                    obj1Md5 = MD5.md5(obj1.toString());
                    obj2Md5 = MD5.md5(obj2.toString());
                } catch (Exception e) {
                    log.info("md5异常了。异常信息为:{}",e.getMessage(),e);
                }
                //不相同vo2就设置成自己的。相同vo2就设置为空
                if(!obj1Md5.equals(obj2Md5)){
                    log.info("不同,vo2的值就设置成自己的");
                    PropertyReflectUtil.setProperty(vo2,filed,obj2);
                }else{
                    log.info("相同,vo2的值就设置成空");
                    PropertyReflectUtil.setProperty(vo2,filed,null);
                }
            }else{
                log.info("其中一个为空.不处理");
            }
        }
    }
}



PropertyReflectUtil工具类:
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 属性反射
 * @author kaigejava
 */
@Slf4j
public class PropertyReflectUtil {
    private static final String SET_PREFIX = "set";
    private static final String IS_PREFIX = "is";
    private static final String GET_PREFIX = "get";

    static String regex=".*\\d+.*";
    /**
     * 判断字符串中是否包含数字
     * @return
     */
    public static boolean strContainsNum(String str){
        if(StringUtils.isBlank(str)){
            return false;
        }
        Pattern pattern=Pattern.compile(regex);
        Matcher matcher=pattern.matcher(str);
        if(matcher.matches()){
            return true;
        }
        return false;
    }

    /**
     * 根据需求,定制 自己的get和set方法
     * @param clazz
     * @param propertyName
     * @return
     */
    public static PropertyDescriptor getPropertyDescriptor(Class<?> clazz, String propertyName) {
        Method setMethod = null;
        Method getMethod = null;
        PropertyDescriptor pd = null;
        try {
            // 根据字段名来获取字段
            Field field = clazz.getDeclaredField(propertyName);
            if (field != null) {
                // 构建方法的后缀
                String methodEnd = propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1);
                setMethod = clazz.getDeclaredMethod(SET_PREFIX + methodEnd, new Class[] { field.getType() });
                // 构建get 方法
                getMethod = clazz.getDeclaredMethod(GET_PREFIX + methodEnd, new Class[] {});
                // 构建一个属性描述器 把对应属性 propertyName 的 get 和 set 方法保存到属性描述器中
                pd = new PropertyDescriptor(propertyName, getMethod, setMethod);
            }
        } catch (Exception ex) {
            log.error("getPropertyDescriptor error,msg:"+ex.getMessage());
        }

        return pd;
    }

    public static PropertyDescriptor getPropertyDescriptor2(Class<?> clazz, String propertyName) {//使用 PropertyDescriptor 提供的 get和set方法
        try {
            return new PropertyDescriptor(propertyName, clazz);
        } catch (IntrospectionException e) {
            log.error(" getPropertyDescriptor2 error,msg:"+e.getMessage());
        }
        return null;
    }

    /**
     * set值
     * @param obj
     * @param propertyName
     * @param value
     */
    public static void setProperty(Object obj, String propertyName, Object value) {
        // 获取对象的类型
        Class<?> clazz = obj.getClass();
        //字段中的下划线处理
        propertyName = formatProperty(propertyName);
        // 获取 clazz类型中的propertyName的属性描述器
        PropertyDescriptor pd = getPropertyDescriptor(clazz, propertyName);
        // 从属性描述器中获取 set 方法
        Method setMethod = pd.getWriteMethod();
        try {
            // 调用 set 方法将传入的value值保存属性中去
            setMethod.invoke(obj, new Object[] { value });
        } catch (Exception e) {
            log.error(" setProperty error,msg:"+e.getMessage());
        }
    }




    /**
     * 获取值
     * @param obj
     * @param propertyName
     * @return
     */
    public static Object getProperty(Object obj, String propertyName) {
        // 获取对象的类型
        Class<?> clazz = obj.getClass();
        //字段中的下划线处理
        propertyName = formatProperty(propertyName);
        // 获取clazz类型中的propertyName的属性描述器
        PropertyDescriptor pd = getPropertyDescriptor(clazz, propertyName);
        // 从属性描述器中获取 get 方法
        Method getMethod = pd.getReadMethod();
        Object value = null;
        try {
            // 调用方法获取方法的返回值
            value = getMethod.invoke(obj, new Object[] {});
        } catch (Exception e) {
            log.error(" getProperty error,msg:{},propertyName:{}",e.getMessage(),propertyName);
        }
        return value;
    }


    /**
     * 根据对象及属性名称获取到对应属性的类型
     * @param obj
     * @param propertyName
     * @return
     */
    public static String getPropertyType(Object obj, String propertyName){
        // 获取对象的类型
        Class<?> clazz = obj.getClass();
        String type = "";
        try {
            // 根据字段名来获取字段
            Field field = clazz.getDeclaredField(propertyName);
            if (field != null) {
                type = field.getGenericType().toString();
            }
        } catch (Exception ex) {
            log.error("getPropertyType error,msg:"+ex.getMessage());
        }

        return type;
    }

    public static String formatProperty(String propertyName) {
        if (propertyName.contains("_")) {
            String[] tmp = propertyName.split("_");
            StringBuilder sb = new StringBuilder();
            sb.append(tmp[0]);
            for (int i = 1; i < tmp.length; i++) {
                sb.append(tmp[i].substring(0, 1).toUpperCase()).append(tmp[i].substring(1));
            }
            return sb.toString();
        } else {
            return propertyName;
        }
    }

}















TopTop