目录
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);
}
}
如有疑问和更改的实现建议欢迎在评论区讨论~