【工具】对象工具类

用于对象的深拷贝、合并等

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * @Author jhlin
 * @DATE 2021/10/12 10:53
 */
public class BeanUtils {
    private static final Logger logger = LoggerFactory.getLogger(BeanUtils.class);
    /**
     * 拷贝对象方法(适合同一类型的对象复制,但结果需强制转换)
     *
     * @throws IllegalAccessException
     * @throws InstantiationException
     */
    public static Object copy(Object objSource) throws InstantiationException, IllegalAccessException{
        return copy(objSource,objSource.getClass());
    }

    /**
     * 拷贝对象方法(适合同一类型的对象复制)
     *
     * @param objSource 源对象
     * @param clazz 目标类
     * @return
     * @throws InstantiationException
     * @throws IllegalAccessException
     */
    public static <T> T copy(Object objSource,Class<T> clazz) throws InstantiationException, IllegalAccessException{

        if(null == objSource) return null;//如果源对象为空,则直接返回null

        T objDes = clazz.newInstance();

        // 获得源对象所有属性
        Field[] fields = clazz.getDeclaredFields();

        // 循环遍历字段,获取字段对应的属性值
        for ( Field field : fields )
        {
            // 如果不为空,设置可见性,然后返回
            field.setAccessible( true );

            try
            {
                field.set(objDes, field.get(objSource));
            }
            catch ( Exception e )
            {
                logger.error("执行{}类的{}属性的set方法时出错。{}",clazz.getSimpleName(),field.getName(),e);
            }
        }
        return objDes;
    }

    /**
     * 拷贝对象方法(适合不同类型的转换)<br/>
     * 前提是,源类中的所有属性在目标类中都存在
     *
     * @param objSource 源对象
     * @param clazzSrc 源对象所属class
     * @param clazzDes 目标class
     * @return
     * @throws InstantiationException
     * @throws IllegalAccessException
     */
    public static <T, K> T copy(K objSource,Class<K> clazzSrc,Class<T> clazzDes ) throws InstantiationException, IllegalAccessException{

        if(null == objSource) return null;//如果源对象为空,则直接返回null

        T objDes = clazzDes.newInstance();

        return merge(objSource, objDes, clazzSrc, clazzDes);

    }


    /**
     * 合并对象方法(适合不同类型的转换)<br/>
     * 前提是,源类中的所有属性在目标类中都存在
     *
     * @param objSource 源对象
     * @param clazzSrc 源对象所属class
     * @param clazzDes 目标class
     * @return
     * @throws InstantiationException
     * @throws IllegalAccessException
     */
    public static <T, K> T merge(K objSource,T objDes,Class<K> clazzSrc,Class<T> clazzDes) throws InstantiationException, IllegalAccessException{
        return merge(objSource, objDes, clazzSrc,clazzDes, true);
    }

    /**
     * 合并对象方法(适合不同类型的转换)<br/>
     * 前提是,源类中的所有属性在目标类中都存在
     *
     * @param objSource 源对象
     * @param clazzSrc 源对象所属class
     * @param clazzDes 目标class
     * @param overwrite 是否覆盖已存在的属性值
     * @return
     * @throws InstantiationException
     * @throws IllegalAccessException
     */
    public static <T, K> T merge(K objSource,T objDes,Class<K> clazzSrc,Class<T> clazzDes,boolean overwrite) throws InstantiationException, IllegalAccessException{
        return merge(objSource,  objDes, clazzSrc,clazzDes, overwrite,null);
    }

    /**
     * 合并对象方法(适合不同类型的转换)<br/>
     * 前提是,源类中的所有属性在目标类中都存在
     *
     * @param objSource 源对象
     * @param objDes 目标对象
     * @param clazzSrc 源对象所属class
     * @param clazzDes 目标class
     * @param overwrite 是否覆盖已存在的属性值
     * @return
     * @throws InstantiationException
     * @throws IllegalAccessException
     */
    public static <T, K> T merge(K objSource, T objDes, Class<K> clazzSrc, Class<T> clazzDes, boolean overwrite, Set<String> IgnoreSet) throws InstantiationException, IllegalAccessException{

        if(null == objSource) return null;//如果源对象为空,则直接返回null

        //获取目标对象的所有属性
        Field[] fieldDeses = clazzDes.getDeclaredFields();
        Map<String,Field> m = new HashMap<String, Field>();
        // 循环遍历字段,获取字段对应的属性值
        for ( Field field : fieldDeses )
        {
            // 如果不为空,设置可见性,然后返回
            field.setAccessible( true );
            m.put(field.getName(), field);
        }


        // 获得源对象所有属性
        Field[] fields = clazzSrc.getDeclaredFields();
        // 循环遍历字段,获取字段对应的属性值
        for ( Field field : fields )
        {
            //如果目标对象不存在该字段,则跳过
            if(!m.containsKey(field.getName())) continue;

            // 如果不为空,设置可见性,然后返回
            field.setAccessible( true );

            try
            {
                String fieldName = field.getName();// 属性名
                String firstLetter = fieldName.substring(0, 1).toUpperCase();// 获取属性首字母

                // 拼接set方法名
                String setMethodName = "set" + firstLetter + fieldName.substring(1);
                // 获取set方法对象
                Method setMethod = clazzDes.getMethod(setMethodName,new Class[]{field.getType()});

                //如果目标对象当前属性不为空
                if(null!=m.get(fieldName).get(objDes)){
                    if(overwrite){//如果覆盖当前属性值,但map中存在,则不覆盖,否则覆盖
                        if(null!=IgnoreSet && IgnoreSet.contains(fieldName.toUpperCase())){//如果map中有值
                            continue;
                        }
                    }else{//如果不覆盖,但是map存在,则必须覆盖,否则不覆盖
                        if(null==IgnoreSet || !IgnoreSet.contains(fieldName.toUpperCase())){//如果map中没有值
                            continue;
                        }
                    }
                }
                // 对目标对象调用set方法装入属性值
                setMethod.invoke(objDes, field.get(objSource));
            }
            catch ( Exception e )
            {
                logger.error("执行{}类的{}属性的set方法时出错。{}",clazzDes.getSimpleName(),field.getName(),e);
            }
        }
        return objDes;
    }


    public static <T> List<T> deepCopy(List<T> src)  {
        try {
            ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
            ObjectOutputStream out = new ObjectOutputStream(byteOut);
            out.writeObject(src);

            ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray());
            ObjectInputStream in = new ObjectInputStream(byteIn);
            @SuppressWarnings("unchecked")
            List<T> dest = (List<T>) in.readObject();
            return dest;
        }catch (Exception e){
            e.printStackTrace();
            return src;
        }

    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值