Java实现实体类拷贝[深,很深的那种...]

目录

说明

Copy类,此类为包内部类,不对外提供调用方法

BaseEntityCopy类,此类以通过实体类继承的方式调用方法

SimpleEntityCopier类型,此类以调用静态方法的方式使用,即第一种方法

EntityCopier类,此类以创建对象的形式使用,对应第二种方法,可对指定字段进行值重写


说明

一共分为两种

第一种是静态调用,适用一般场景

第二种需要new对象调用,支持在拷贝过程中对指定字段值进行重写

第二种方法是在类内主动格式化已列举的数据类型,如有其他类型格式需求则需在Parse类中自主扩展添加

记得改一下引用类所在的包

Demo项目已经上传,里面包含所有代码和使用方法,各位可先查阅本文代码部分后自行决定是否需要下载Demo


代码展示部分

Copy类,此类为包内部类,不对外提供调用方法

import java.lang.reflect.Field;

/**
 * @author Canser
 */
public class Copy {

    protected static <ORIGIN, TARGET> void foreach(Field[] targetFields, Class<?> originClass, TARGET target, ORIGIN origin)
            throws Exception {
        for (Field targetField : targetFields) {
            if (EntityCopier.skip(targetField)) {
                continue;
            }
            targetField.setAccessible(true);
            String targetFieldName = targetField.getName();

            Field origField;
            try {
                origField = originClass.getDeclaredField(targetFieldName);
                origField.setAccessible(true);
            } catch (Exception ignored) {
                continue;
            }

            Object val = origField.get(origin);
            if (val == null) {
                continue;
            }

            targetField.set(target, origField.getType() == targetField.getType() ? val : Parse.parse(targetField, val));
        }
    }

}

BaseEntityCopy类,此类以通过实体类继承的方式调用方法

import java.lang.reflect.Field;

/**
 * @author Canser
 */
public class BaseEntityCopy {

    public <TARGET> TARGET copyTo(Class<TARGET> targetClass) {
        Field[] targetFields = targetClass.getDeclaredFields();
        Class<?> originClass = this.getClass();
        try {
            TARGET target = targetClass.getConstructor().newInstance();
            Copy.foreach(targetFields, originClass, target, this);
            return target;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public <ORIGIN, TARGET> EntityCopier<ORIGIN, TARGET> buildCopier(Class<TARGET> targetClass) {
        return new EntityCopier<ORIGIN, TARGET>(targetClass).set((ORIGIN) this);
    }

}

SimpleEntityCopier类型,此类以调用静态方法的方式使用,即第一种方法

import java.lang.reflect.Field;

/**
 * @author Canser
 */
public class SimpleEntityCopier {

    public static <TARGET, ORIGIN> TARGET copyTo(ORIGIN origin, Class<TARGET> targetClass, TARGET def)  {
        try {
            return copyTo(origin, targetClass);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return def;
    }

    public static <TARGET, ORIGIN> TARGET copyTo(ORIGIN origin, Class<TARGET> targetClass) throws Exception {
        Field[] targetFields = targetClass.getDeclaredFields();
        Class<?> originClass = origin.getClass();
        TARGET target = targetClass.getConstructor().newInstance();

        Copy.foreach(targetFields, originClass, target, origin);
        return target;
    }

}

EntityCopier类,此类以创建对象的形式使用,对应第二种方法,可对指定字段进行值重写

import org.apache.commons.lang3.ObjectUtils;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;

/**
 * @author Canser
 * 通过实例化对象进行拷贝,支持在拷贝过程中对指定属性进行覆写(rewrite)
 * Entity entity = new Entity();
 * EntityCopier<\Entity2> copier = new EntityCopier<\>(Entity2.class);
 * Entity2 entity2 = copier.set(entity)[.rewrite(Entity2::get, "")...].getResult();
 */
public class EntityCopier<ORIGIN, TARGET> {

    // 源数据
    private ORIGIN orig;

    // 目标类
    private final Class<TARGET> targetClass;

    // 目标类的字段
    private Field[] targetFields;

    // 字段值重写数组
    private final HashMap<String, Object> rewriteMap = new HashMap<>();

    /**
     * [公共] 实例化对象
     *
     * @param targetClass 目标数据类
     */
    public EntityCopier(Class<TARGET> targetClass) {
        this.targetClass = targetClass;
        if (targetClass != null) {
            this.targetFields = targetClass.getDeclaredFields();
        }
    }

    /**
     * [公共] 设置源数据对象
     *
     * @param orig 源数据对象
     */
    public EntityCopier<ORIGIN, TARGET> set(ORIGIN orig) {
        this.orig = orig;
        this.rewriteMap.clear();
        return this;
    }

    /**
     * [公共] 为指定字段重新赋自定义值
     *
     * @param func  需要重新赋值的字段
     * @param inter 回调,返回新的值
     */
    public <VAL> EntityCopier<ORIGIN, TARGET> rewriteInter(TFunction<TARGET, VAL> func, CopyCallbackInter<VAL> inter) throws Exception {
        return rewrite(func, inter.back());
    }

    /**
     * [公共] 为指定字段重新赋自定义值
     *
     * @param func 需要重新赋值的字段
     * @param val  需要重新赋的值
     */
    public <VAL> EntityCopier<ORIGIN, TARGET> rewrite(TFunction<TARGET, VAL> func, VAL val) {
        try {
            Field field = (Field) func.getField().get("field");
            rewriteMap.put(field.getName(), Parse.parse(field, val));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return this;
    }

    /**
     * [公共] 获取深拷贝结果
     */
    public TARGET getResult() {
        if (targetFields.length == 0 || ObjectUtils.isEmpty(orig)) {
            return null;
        }
        try {
            TARGET target = this.targetClass.getConstructor().newInstance();
            List<String> origFieldNames = Arrays.stream(orig.getClass().getDeclaredFields()).map(Field::getName).toList();
            Class<?> origClass = orig.getClass();
            for (Field field : targetFields) {
                if (skip(field)) {
                    continue;
                }
                field.setAccessible(true);
                String fieldName = field.getName();
                if (rewriteMap.get(fieldName) != null) {
                    field.set(target, rewriteMap.get(fieldName));
                } else if (origFieldNames.contains(fieldName)) {
                    set(origClass.getDeclaredField(fieldName), field, target);
                }
            }
            return target;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            this.orig = null;
            this.rewriteMap.clear();
        }
        return null;
    }

    /**
     * [内部] 字段赋值
     *
     * @param origField   源数据字段
     * @param targetField 目标数据字段
     * @param target      目标数据对象
     */
    private void set(Field origField, Field targetField, TARGET target) {
        try {
            origField.setAccessible(true);
            Object val = origField.get(orig);
            if (origField.getType() == targetField.getType()) {
                targetField.set(target, val);
                return;
            }
            targetField.set(target, Parse.parse(targetField, val));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 判断字段是否可读写(不可读写指修饰符为private+static+final的字段)
     *
     * @param field 需要判断的字段对象
     * @return 返回字段是否可读写
     */
    public static boolean skip(Field field) {
        int modifiers = field.getModifiers();
        int declareModifiers = field.getDeclaringClass().getModifiers();
        return (!Modifier.isPublic(modifiers) || !Modifier.isPublic(declareModifiers)) && Modifier.isFinal(modifiers);
    }

}

其他类

CopyCallbackInter类

/**
 * @author Canser
 */
@FunctionalInterface
public interface CopyCallbackInter<VAL> {

    VAL back() throws Exception;

}

TFunction类

import java.io.Serializable;
import java.lang.invoke.SerializedLambda;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.function.Function;

/**
 * @author Canser
 */
@FunctionalInterface
public interface TFunction<T, R> extends Function<T, R>, Serializable {

    /**
     * 获取属性对象和属性名
     */
    default HashMap<String, Object> getField() throws Exception {
        // 从function取出序列化方法
        Method writeReplaceMethod = this.getClass().getDeclaredMethod("writeReplace");

        // 从序列化方法取出序列化的lambda信息
        writeReplaceMethod.setAccessible(true);

        SerializedLambda serializedLambda = (SerializedLambda) writeReplaceMethod.invoke(this);

        // 从lambda信息取出method、field、class等
        String fieldName = serializedLambda.getImplMethodName().substring("get".length());
        fieldName = fieldName.replaceFirst(fieldName.charAt(0) + "", (fieldName.charAt(0) + "").toLowerCase());
        Field field = Class.forName(serializedLambda.getImplClass().replace("/", ".")).getDeclaredField(fieldName);
        String finalFieldName = fieldName;
        return new HashMap<>(2) {{
            this.put("fieldName", finalFieldName);
            this.put("field", field);
        }};

    }

}

Parse类,可通用

import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.*;

/**
 * @author Canser
 *
 * 数据格式化工具类
 * 这个类是个体力活,有需要进行指定转换的就要手动添加
 * [任意类型] 可转
 * String, Integer, Double, Long, Boolean, Float, Byte, Character, Short,
 * java.util.Date, java.sql.Date, LocalDate, LocalTime, LocalDateTime
 * LocalDate可转LocalDateTime,LocalTime不可转LocalDateTime
 */
public class Parse {

    /**
     * 自定义格式化方法参数接口
     */
    @FunctionalInterface
    public interface Inter<T> {
        T func();
    }

    /**
     * 根据字段类型格式化对象, 未找到满足的格式化类型时返回数据不强转
     */
    public static Object parse(Field field, Object val) {
        return parse(field, val, false);
    }

    /**
     * 根据字段类型格式化对象, 未找到满足的格式化类型时返回数据进行强转,可能返回null
     */
    public static Object parse(Field field, Object val, boolean allowCast) {
        if (val == null) {
            return null;
        }
        Type type = field.getType();
        if (type == Object.class) {
            return val;
        }
        if (type == String.class) {
            return parseToString(val);
        }
        if (type == Integer.class || type == int.class) {
            return parseToInt(val);
        }
        if (type == Double.class || type == double.class) {
            return parseToDouble(val);
        }
        if (type == Long.class || type == long.class) {
            return parseToLong(val);
        }
        if (type == Boolean.class || type == boolean.class) {
            return parseToBoolean(val);
        }
        if (type == Float.class || type == float.class) {
            return parseToFloat(val);
        }
        if (type == Byte.class || type == byte.class) {
            return parseToByte(val);
        }
        if (type == Character.class || type == char.class) {
            return parseToChar(val);
        }
        if (type == Short.class || type == short.class) {
            return parseToShort(val);
        }
        if (type == java.sql.Date.class) {
            return parseDate(val);
        }
        if (type == Date.class) {
            return parseUtilDateToSqlDate(val);
        }
        if (type == LocalDateTime.class) {
            return parseToLocalDateTime(val);
        }
        if (type == LocalDate.class) {
            return parseToLocalDate(val);
        }
        if (type == LocalTime.class) {
            return parseToLocalTime(val);
        }

        List<Class<?>> list = Arrays.asList(field.getType().getInterfaces());
        if (list.contains(List.class)) {
            return parseSetToList(val);
        } else if (list.contains(Set.class)) {
            return parsetListToSet(val);
        }

        return allowCast ? castParse(val) : val;
    }

    public static <T> T parse(Inter<T> inter, T expRes) {
        try {
            return inter.func();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return expRes;
    }

    public static String parseToString(Object obj) {
        return parse(obj::toString, "");
    }

    public static Boolean parseToBoolean(Object obj) {
        return parse(() -> Boolean.parseBoolean(obj.toString()), false);
    }

    /**
     * 格式化为int类型
     */
    public static Integer parseToInt(Object obj) {
        return parse(() -> Integer.parseInt(obj.toString()), 0);
    }

    /**
     * 格式化为Long类型
     */
    public static Long parseToLong(Object obj) {
        return parse(() -> Long.parseLong(obj.toString()), 0L);
    }

    /**
     * 格式化为Double类型
     */
    public static Double parseToDouble(Object obj) {
        return parse(() -> Double.parseDouble(obj.toString()), 0.0);
    }

    /**
     * 格式化为Float类型
     */
    public static Float parseToFloat(Object obj) {
        return parse(() -> Float.parseFloat(obj.toString()), 0F);
    }

    /**
     * 格式化为Byte类型
     */
    public static Byte parseToByte(Object obj) {
        return parse(() -> Byte.parseByte(obj.toString()), (byte) 0);
    }

    /**
     * 格式化为Short类型
     */
    public static Short parseToShort(Object obj) {
        return parse(() -> Short.parseShort(obj.toString()), (short) 0);
    }

    /**
     * 格式化为Character类型
     */
    public static Character parseToChar(Object obj) {
        return parse(() -> obj.toString().charAt(0), (char) 0);
    }

    /**
     * 将List格式化为Set类型
     * 基本用不到
     */
    private static List<?> parseSetToList(Object obj) {
        return parse(() -> new ArrayList<>((Set<?>) obj), new ArrayList<>());
    }

    /**
     * 将List格式化为Set类型
     * 基本用不到
     */
    private static Set<?> parsetListToSet(Object obj) {
        return parse(() -> new HashSet<>((List<?>) obj), new HashSet<>());
    }

    /**
     * 格式化为Date类型
     */
    public static Date parseDate(Object obj) {
        return parse(() -> (Date) obj, null);
    }

    /**
     * 将java.sql.Date格式化为java.util.Date类型
     */
    public static Date parseUtilDateToSqlDate(Object obj) {
        return parse(() -> new Date(((Date) obj).getTime()), null);
    }

    /**
     * 格式化为LocalDateTime类型
     */
    public static LocalDateTime parseToLocalDateTime(Object obj) {
        if (obj instanceof LocalDate) {
            return ((LocalDate) obj).atStartOfDay();
        }
        return parse(() -> LocalDateTime.parse(obj.toString()), null);
    }

    /**
     * 格式化为LocalDate类型
     */
    public static LocalDate parseToLocalDate(Object val) {
        return parse(() -> LocalDate.parse(val.toString()), null);
    }

    /**
     * 格式化为LocalTime类型
     */
    public static LocalTime parseToLocalTime(Object val) {
        return parse(() -> LocalTime.parse(val.toString()), null);
    }

    /**
     * 强制转化对象,如转化失败,则返回null
     *
     * @param <T>
     */
    @SuppressWarnings("unchecked")
    public static <T> T castParse(Object obj) {
        return parse(() -> (T) obj, null);
    }

}

如有疑问和更改的实现建议欢迎在评论区讨论~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

胡#

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值