判断两个对象某些字段的值是否相同

发布时间:2024年01月10日

1、借助mybatis plus的方法

import com.baomidou.mybatisplus.core.toolkit.LambdaUtils;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.baomidou.mybatisplus.core.toolkit.support.SerializedLambda;
import lombok.SneakyThrows;
import org.apache.ibatis.reflection.property.PropertyNamer;

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

public class ObjectUtil {

    /**
     * 判断两个对象的某些字段的值是否相等
     * @param newObj 新对象
     * @param oldObj 旧对象
     * @param functions 函数式接口数组
     * @param <T> 泛型T
     * @return 两个对象某些字段的值是否相等
     */
    @SafeVarargs
    @SneakyThrows
    public static <T> boolean isSame(Object newObj,Object oldObj,SFunction<T,?>... functions){
        for(SFunction<T,?> function:functions){
            Field newField=newObj.getClass().getField(getField(function));
            Field oldField=oldObj.getClass().getField(getField(function));
            newField.setAccessible(true);
            oldField.setAccessible(true);
            if(!Objects.equals(newField.get(newObj),oldField.get(oldObj))){
                return false;
            }
        }
        return true;
    }

    /**
     * 判断两个对象的某些字段的值是否相等
     * @param newObj 新对象
     * @param oldObj 旧对象
     * @param fields 字段数组
     * @return 是否相等
     */
    @SneakyThrows
    public static boolean isSame(Object newObj,Object oldObj,String... fields){
        for(String filed:fields){
            Field newField=newObj.getClass().getField(filed);
            Field oldField=oldObj.getClass().getField(filed);
            newField.setAccessible(true);
            oldField.setAccessible(true);
            if(!Objects.equals(newField.get(newObj),oldField.get(oldObj))){
                return false;
            }
        }
        return true;
    }

    /**
     * 根据函数式接口的方法获取字段名称
     * @param sFunction 函数式接口
     * @param <T> 泛型T
     * @return 字段名称
     */
    public static <T> String getField(SFunction<T,?> sFunction){
        return getColumn(LambdaUtils.resolve(sFunction));
    }

    /**
     *
     * @param serializedLambda 函数式接口的Lambda表达式
     * @return 字段名
     */
    public static String getColumn(SerializedLambda serializedLambda){
        return PropertyNamer.methodToProperty(serializedLambda.getImplMethodName());
    }

}

既可以直接输入字段名,也可以输入Lambda表达式获取字段名

2、自己手写函数式接口完成从Lambda表达式到字段名的解析

? ?2.1 先定义可以序列化的函数式接口

import java.io.Serializable;
import java.util.function.Function;

@FunctionalInterface
public interface MFunction<T, R> extends Function<T, R>, Serializable {

}

? 2.2 根据可以序列化的函数式接口解析字段名

? ? ? ? ?




import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.property.PropertyNamer;
import java.lang.invoke.SerializedLambda;
import java.lang.reflect.Method;

@Slf4j
public class LambdaUtil {

    /**
     *
     * @param serializedLambda 函数式接口的Lambda表达式
     * @return 字段名
     */
    public static String getColumn(SerializedLambda serializedLambda) {
        return PropertyNamer.methodToProperty(serializedLambda.getImplMethodName());
    }

    /**
     * 根据函数式接口获取字段名成
     * @param func 函数式接口,例:User::getId()
     * @param <T> 泛型T
     * @param <R> 泛型R
     * @return 字段名
     */
    @SneakyThrows
    private static <T, R> String getColumn(MFunction<T, R> func) {
        // 直接调用writeReplace
        Method writeReplace = func.getClass().getDeclaredMethod("writeReplace");
        writeReplace.setAccessible(true);
        //反射调用
        Object sl = writeReplace.invoke(func);
        return getColumn((java.lang.invoke.SerializedLambda) sl);
    }

}

文章来源:https://blog.csdn.net/weixin_42502300/article/details/135511366
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。