mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-05-09 23:51:34 +08:00
fix typeUtil
This commit is contained in:
parent
3e05c5b396
commit
784ad3e8f9
@ -15,7 +15,7 @@
|
||||
* 【extra 】 SpringUtil增加注册bean(pr#174@Gitee)
|
||||
* 【core 】 修改NetUtil.getMacAddress避免空指针(issue#1057@Github)
|
||||
* 【core 】 增加EnumItem接口,枚举扩展转换,增加SPI自定义转换(pr#173@Github)
|
||||
* 【core 】 TypeUtil增加getActualTypeMap方法
|
||||
* 【core 】 TypeUtil增加getActualType,增加ActualTypeMapperPool类(issue#I1TBWH@Gitee)
|
||||
|
||||
### Bug修复
|
||||
* 【core 】 重新整理农历节假日,解决一个pr过来的玩笑导致的问题
|
||||
|
@ -7,10 +7,8 @@ import cn.hutool.core.bean.copier.provider.MapValueProvider;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import cn.hutool.core.exceptions.UtilException;
|
||||
import cn.hutool.core.lang.ParameterizedTypeImpl;
|
||||
import cn.hutool.core.lang.copier.Copier;
|
||||
import cn.hutool.core.map.MapUtil;
|
||||
import cn.hutool.core.util.ArrayUtil;
|
||||
import cn.hutool.core.util.ModifierUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
@ -19,9 +17,7 @@ import cn.hutool.core.util.TypeUtil;
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.lang.reflect.TypeVariable;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
@ -246,24 +242,8 @@ public class BeanCopier<T> implements Copier<T>, Serializable {
|
||||
|
||||
// 获取目标字段真实类型
|
||||
Type fieldType = (null == setterMethod) ? TypeUtil.getType(field) : TypeUtil.getFirstParamType(setterMethod);
|
||||
if (fieldType instanceof ParameterizedType) {
|
||||
// 字段类型为泛型参数类型,解析对应泛型类型为真实类型,类似于List<T> a
|
||||
final ParameterizedType fieldParameterizedType = (ParameterizedType) fieldType;
|
||||
Type[] actualTypeArguments = fieldParameterizedType.getActualTypeArguments();
|
||||
if (TypeUtil.hasTypeVeriable(actualTypeArguments)) {
|
||||
// 泛型对象中含有未被转换的泛型变量
|
||||
actualTypeArguments = TypeUtil.getActualTypes(this.destType, field.getDeclaringClass(), fieldParameterizedType.getActualTypeArguments());
|
||||
if (ArrayUtil.isNotEmpty(actualTypeArguments)) {
|
||||
// 替换泛型变量为实际类型
|
||||
fieldType = new ParameterizedTypeImpl(actualTypeArguments, fieldParameterizedType.getOwnerType(), fieldParameterizedType.getRawType());
|
||||
}
|
||||
}
|
||||
} else if (fieldType instanceof TypeVariable) {
|
||||
// 字段类型为泛型,查找其真实类型(适用于泛型方法定义于泛型父类),类似于T a
|
||||
fieldType = TypeUtil.getActualType(this.destType, field.getDeclaringClass(), fieldType);
|
||||
}
|
||||
fieldType = TypeUtil.getActualType(this.destType ,fieldType);
|
||||
|
||||
//
|
||||
value = valueProvider.value(providerKey, fieldType);
|
||||
if (null == value && copyOptions.ignoreNullValue) {
|
||||
continue;// 当允许跳过空时,跳过
|
||||
|
@ -2023,7 +2023,7 @@ public class CollUtil {
|
||||
if (null == collection || null == value) {
|
||||
return collection;
|
||||
}
|
||||
if (TypeUtil.isUnknow(elementType)) {
|
||||
if (TypeUtil.isUnknown(elementType)) {
|
||||
// 元素类型为空时,使用Object类型来接纳所有类型
|
||||
elementType = Object.class;
|
||||
}
|
||||
|
@ -226,14 +226,14 @@ public class ConverterRegistry implements Serializable {
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T convert(Type type, Object value, T defaultValue, boolean isCustomFirst) throws ConvertException {
|
||||
if (TypeUtil.isUnknow(type) && null == defaultValue) {
|
||||
if (TypeUtil.isUnknown(type) && null == defaultValue) {
|
||||
// 对于用户不指定目标类型的情况,返回原值
|
||||
return (T) value;
|
||||
}
|
||||
if (ObjectUtil.isNull(value)) {
|
||||
return defaultValue;
|
||||
}
|
||||
if (TypeUtil.isUnknow(type)) {
|
||||
if (TypeUtil.isUnknown(type)) {
|
||||
type = defaultValue.getClass();
|
||||
}
|
||||
|
||||
|
@ -23,7 +23,7 @@ public class AtomicReferenceConverter extends AbstractConverter<AtomicReference>
|
||||
//尝试将值转换为Reference泛型的类型
|
||||
Object targetValue = null;
|
||||
final Type paramType = TypeUtil.getTypeArgument(AtomicReference.class);
|
||||
if(false == TypeUtil.isUnknow(paramType)){
|
||||
if(false == TypeUtil.isUnknown(paramType)){
|
||||
targetValue = ConverterRegistry.getInstance().convert(paramType, value);
|
||||
}
|
||||
if(null == targetValue){
|
||||
|
@ -86,8 +86,8 @@ public class MapConverter extends AbstractConverter<Map<?, ?>> {
|
||||
Object key;
|
||||
Object value;
|
||||
for (Entry<?, ?> entry : srcMap.entrySet()) {
|
||||
key = TypeUtil.isUnknow(this.keyType) ? entry.getKey() : convert.convert(this.keyType, entry.getKey());
|
||||
value = TypeUtil.isUnknow(this.valueType) ? entry.getValue() : convert.convert(this.valueType, entry.getValue());
|
||||
key = TypeUtil.isUnknown(this.keyType) ? entry.getKey() : convert.convert(this.keyType, entry.getKey());
|
||||
value = TypeUtil.isUnknown(this.valueType) ? entry.getValue() : convert.convert(this.valueType, entry.getValue());
|
||||
targetMap.put(key, value);
|
||||
}
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ public class ReferenceConverter extends AbstractConverter<Reference> {
|
||||
//尝试将值转换为Reference泛型的类型
|
||||
Object targetValue = null;
|
||||
final Type paramType = TypeUtil.getTypeArgument(targetType);
|
||||
if(false == TypeUtil.isUnknow(paramType)){
|
||||
if(false == TypeUtil.isUnknown(paramType)){
|
||||
targetValue = ConverterRegistry.getInstance().convert(paramType, value);
|
||||
}
|
||||
if(null == targetValue){
|
||||
|
@ -359,6 +359,19 @@ public class CalendarUtil {
|
||||
return StrUtil.builder().append(cal.get(Calendar.YEAR)).append(cal.get(Calendar.MONTH) / 3 + 1).toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定日期字段的最小值,例如分钟的最小值是0
|
||||
*
|
||||
* @param calendar {@link Calendar}
|
||||
* @param dateField {@link DateField}
|
||||
* @return 字段最小值
|
||||
* @see Calendar#getActualMinimum(int)
|
||||
* @since 5.4.2
|
||||
*/
|
||||
public static int getBeginValue(Calendar calendar, DateField dateField) {
|
||||
return getBeginValue(calendar, dateField.getValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定日期字段的最小值,例如分钟的最小值是0
|
||||
*
|
||||
@ -375,6 +388,19 @@ public class CalendarUtil {
|
||||
return calendar.getActualMinimum(dateField);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定日期字段的最大值,例如分钟的最大值是59
|
||||
*
|
||||
* @param calendar {@link Calendar}
|
||||
* @param dateField {@link DateField}
|
||||
* @return 字段最大值
|
||||
* @see Calendar#getActualMaximum(int)
|
||||
* @since 5.4.2
|
||||
*/
|
||||
public static int getEndValue(Calendar calendar, DateField dateField) {
|
||||
return getEndValue(calendar, dateField.getValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定日期字段的最大值,例如分钟的最大值是59
|
||||
*
|
||||
|
@ -1916,6 +1916,18 @@ public class DateUtil extends CalendarUtil {
|
||||
return Year.of(year).length();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得指定月份的总天数
|
||||
*
|
||||
* @param month 年份
|
||||
* @param isLeapYear 是否闰年
|
||||
* @return 天
|
||||
* @since 5.4.2
|
||||
*/
|
||||
public static int lengthOfMonth(int month, boolean isLeapYear) {
|
||||
return java.time.Month.of(month).length(isLeapYear);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------ Private method start
|
||||
|
||||
/**
|
||||
|
@ -0,0 +1,101 @@
|
||||
package cn.hutool.core.lang.reflect;
|
||||
|
||||
import cn.hutool.core.lang.SimpleCache;
|
||||
import cn.hutool.core.util.TypeUtil;
|
||||
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.lang.reflect.TypeVariable;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 泛型变量和泛型实际类型映射关系缓存
|
||||
*
|
||||
* @author looly
|
||||
* @since 5.4.2
|
||||
*/
|
||||
public class ActualTypeMapperPool {
|
||||
|
||||
private static final SimpleCache<Type, Map<Type, Type>> cache = new SimpleCache<>();
|
||||
|
||||
/**
|
||||
* 获取泛型变量和泛型实际类型的对应关系Map
|
||||
*
|
||||
* @param type 被解析的包含泛型参数的类
|
||||
* @return 泛型对应关系Map
|
||||
*/
|
||||
public static Map<Type, Type> get(Type type) {
|
||||
return cache.get(type, () -> createTypeMap(type));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得泛型变量对应的泛型实际类型,如果此变量没有对应的实际类型,返回null
|
||||
*
|
||||
* @param type 类
|
||||
* @param typeVariable 泛型变量,例如T等
|
||||
* @return 实际类型,可能为Class等
|
||||
*/
|
||||
public static Type getActualType(Type type, TypeVariable<?> typeVariable) {
|
||||
final Map<Type, Type> typeTypeMap = get(type);
|
||||
Type result = typeTypeMap.get(typeVariable);
|
||||
while (result instanceof TypeVariable) {
|
||||
result = typeTypeMap.get(result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定泛型变量对应的真实类型<br>
|
||||
* 由于子类中泛型参数实现和父类(接口)中泛型定义位置是一一对应的,因此可以通过对应关系找到泛型实现类型<br>
|
||||
*
|
||||
* @param type 真实类型所在类,此类中记录了泛型参数对应的实际类型
|
||||
* @param typeVariables 泛型变量,需要的实际类型对应的泛型参数
|
||||
* @return 给定泛型参数对应的实际类型,如果无对应类型,对应位置返回null
|
||||
*/
|
||||
public static Type[] getActualTypes(Type type, Type... typeVariables) {
|
||||
// 查找方法定义所在类或接口中此泛型参数的位置
|
||||
final Type[] result = new Type[typeVariables.length];
|
||||
for (int i = 0; i < typeVariables.length; i++) {
|
||||
result[i] = (typeVariables[i] instanceof TypeVariable)
|
||||
? getActualType(type, (TypeVariable<?>) typeVariables[i])
|
||||
: typeVariables[i];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建类中所有的泛型变量和泛型实际类型的对应关系Map
|
||||
*
|
||||
* @param type 被解析的包含泛型参数的类
|
||||
* @return 泛型对应关系Map
|
||||
*/
|
||||
private static Map<Type, Type> createTypeMap(Type type) {
|
||||
final Map<Type, Type> typeMap = new HashMap<>();
|
||||
|
||||
// 按继承层级寻找泛型变量和实际类型的对应关系
|
||||
// 在类中,对应关系分为两类:
|
||||
// 1. 父类定义变量,子类标注实际类型
|
||||
// 2. 父类定义变量,子类继承这个变量,让子类的子类去标注,以此类推
|
||||
// 此方法中我们将每一层级的对应关系全部加入到Map中,查找实际类型的时候,根据传入的泛型变量,
|
||||
// 找到对应关系,如果对应的是继承的泛型变量,则递归继续找,直到找到实际或返回null为止。
|
||||
// 如果传入的非Class,例如TypeReference,获取到泛型参数中实际的泛型对象类,继续按照类处理
|
||||
while (null != type) {
|
||||
final ParameterizedType parameterizedType = TypeUtil.toParameterizedType(type);
|
||||
if(null == parameterizedType){
|
||||
break;
|
||||
}
|
||||
final Type[] typeArguments = parameterizedType.getActualTypeArguments();
|
||||
final Class<?> rawType = (Class<?>) parameterizedType.getRawType();
|
||||
final Type[] typeParameters = rawType.getTypeParameters();
|
||||
|
||||
for (int i = 0; i < typeParameters.length; i++) {
|
||||
typeMap.put(typeParameters[i], typeArguments[i]);
|
||||
}
|
||||
|
||||
type = rawType;
|
||||
}
|
||||
|
||||
return typeMap;
|
||||
}
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
/**
|
||||
* 提供反射相关功能对象和类
|
||||
*
|
||||
* @author looly
|
||||
* @since 5.4.2
|
||||
*/
|
||||
package cn.hutool.core.lang.reflect;
|
@ -1,6 +1,7 @@
|
||||
package cn.hutool.core.util;
|
||||
|
||||
import cn.hutool.core.map.TableMap;
|
||||
import cn.hutool.core.lang.ParameterizedTypeImpl;
|
||||
import cn.hutool.core.lang.reflect.ActualTypeMapperPool;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
@ -8,6 +9,7 @@ import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.lang.reflect.TypeVariable;
|
||||
import java.lang.reflect.WildcardType;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 针对 {@link Type} 的工具类封装<br>
|
||||
@ -281,93 +283,6 @@ public class TypeUtil {
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取泛型变量和真实类型的对应表,使用{@link TableMap}表示,key不会重复<br>
|
||||
* 由于子类中泛型参数实现和父类(接口)中泛型定义位置是一一对应的,因此可以通过对应关系找到泛型实现类型<br>
|
||||
* 使用此方法注意:
|
||||
*
|
||||
* <pre>
|
||||
* 1. typeDefineClass必须是clazz的父类或者clazz实现的接口
|
||||
* </pre>
|
||||
*
|
||||
* @param actualType 真实类型所在类,此类中记录了泛型参数对应的实际类型
|
||||
* @param typeDefineClass 泛型变量声明所在类或接口,此类中定义了泛型类型
|
||||
* @return 给定泛型参数对应的实际类型,如果无对应类型,返回null
|
||||
* @since 5.4.1
|
||||
*/
|
||||
public static TableMap<String, Type> getActualTypeMap(Type actualType, Class<?> typeDefineClass) {
|
||||
if (false == typeDefineClass.isAssignableFrom(getClass(actualType))) {
|
||||
throw new IllegalArgumentException("Parameter [superClass] must be assignable from [clazz]");
|
||||
}
|
||||
|
||||
// 泛型参数标识符列表
|
||||
final TypeVariable<?>[] typeVars = typeDefineClass.getTypeParameters();
|
||||
if (ArrayUtil.isEmpty(typeVars)) {
|
||||
return new TableMap<>(0);
|
||||
}
|
||||
|
||||
// 实际类型列表
|
||||
final Type[] actualTypeArguments = TypeUtil.getTypeArguments(actualType);
|
||||
if (ArrayUtil.isEmpty(actualTypeArguments)) {
|
||||
return new TableMap<>(0);
|
||||
}
|
||||
|
||||
return new TableMap<>(ArrayUtil.map(typeVars, String.class, TypeVariable::getName), actualTypeArguments);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定泛型变量对应的真实类型<br>
|
||||
* 由于子类中泛型参数实现和父类(接口)中泛型定义位置是一一对应的,因此可以通过对应关系找到泛型实现类型<br>
|
||||
* 使用此方法注意:
|
||||
*
|
||||
* <pre>
|
||||
* 1. superClass必须是clazz的父类或者clazz实现的接口
|
||||
* 2. typeVariable必须在superClass中声明
|
||||
* </pre>
|
||||
*
|
||||
* @param actualType 真实类型所在类,此类中记录了泛型参数对应的实际类型
|
||||
* @param typeDefineClass 泛型变量声明所在类或接口,此类中定义了泛型类型
|
||||
* @param typeVariables 泛型变量,需要的实际类型对应的泛型参数
|
||||
* @return 给定泛型参数对应的实际类型,如果无对应类型,返回null
|
||||
* @since 4.5.7
|
||||
*/
|
||||
public static Type[] getActualTypes(Type actualType, Class<?> typeDefineClass, Type... typeVariables) {
|
||||
final TableMap<String, Type> tableMap = getActualTypeMap(actualType, typeDefineClass);
|
||||
|
||||
// 查找方法定义所在类或接口中此泛型参数的位置
|
||||
final Type[] result = new Type[typeVariables.length];
|
||||
for (int i = 0; i < typeVariables.length; i++) {
|
||||
result[i] = (typeVariables[i] instanceof TypeVariable)
|
||||
? tableMap.get(((TypeVariable<?>) typeVariables[i]).getName())
|
||||
: typeVariables[i];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定泛型变量对应的真实类型<br>
|
||||
* 由于子类中泛型参数实现和父类(接口)中泛型定义位置是一一对应的,因此可以通过对应关系找到泛型实现类型<br>
|
||||
* 使用此方法注意:
|
||||
*
|
||||
* <pre>
|
||||
* 1. superClass必须是clazz的父类或者clazz实现的接口
|
||||
* 2. typeVariable必须在superClass中声明
|
||||
* </pre>
|
||||
*
|
||||
* @param actualType 真实类型所在类,此类中记录了泛型参数对应的实际类型
|
||||
* @param typeDefineClass 泛型变量声明所在类或接口,此类中定义了泛型类型
|
||||
* @param typeVariable 泛型变量,需要的实际类型对应的泛型参数
|
||||
* @return 给定泛型参数对应的实际类型
|
||||
* @since 4.5.2
|
||||
*/
|
||||
public static Type getActualType(Type actualType, Class<?> typeDefineClass, Type typeVariable) {
|
||||
final Type[] types = getActualTypes(actualType, typeDefineClass, typeVariable);
|
||||
if (ArrayUtil.isNotEmpty(types)) {
|
||||
return types[0];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否未知类型<br>
|
||||
* type为null或者{@link TypeVariable} 都视为未知类型
|
||||
@ -376,7 +291,7 @@ public class TypeUtil {
|
||||
* @return 是否未知类型
|
||||
* @since 4.5.2
|
||||
*/
|
||||
public static boolean isUnknow(Type type) {
|
||||
public static boolean isUnknown(Type type) {
|
||||
return null == type || type instanceof TypeVariable;
|
||||
}
|
||||
|
||||
@ -395,4 +310,84 @@ public class TypeUtil {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取泛型变量和泛型实际类型的对应关系Map
|
||||
*
|
||||
* @param clazz 被解析的包含泛型参数的类
|
||||
* @return 泛型对应关系Map
|
||||
*/
|
||||
public static Map<Type, Type> getTypeMap(Class<?> clazz) {
|
||||
return ActualTypeMapperPool.get(clazz);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得泛型字段对应的泛型实际类型,如果此变量没有对应的实际类型,返回null
|
||||
*
|
||||
* @param type 实际类型明确的类
|
||||
* @param field 字段
|
||||
* @return 实际类型,可能为Class等
|
||||
*/
|
||||
public static Type getActualType(Type type, Field field) {
|
||||
if(null == field){
|
||||
return null;
|
||||
}
|
||||
return getActualType(ObjectUtil.defaultIfNull(type, field.getDeclaringClass()), field.getGenericType());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得泛型变量对应的泛型实际类型,如果此变量没有对应的实际类型,返回null
|
||||
* 此方法可以处理
|
||||
*
|
||||
* @param type 类
|
||||
* @param typeVariable 泛型变量,例如T等
|
||||
* @return 实际类型,可能为Class等
|
||||
*/
|
||||
public static Type getActualType(Type type, Type typeVariable) {
|
||||
if (typeVariable instanceof ParameterizedType) {
|
||||
return getActualType(type, (ParameterizedType)typeVariable);
|
||||
}
|
||||
|
||||
if (typeVariable instanceof TypeVariable) {
|
||||
return ActualTypeMapperPool.getActualType(type, (TypeVariable<?>) typeVariable);
|
||||
}
|
||||
|
||||
// 没有需要替换的泛型变量,原样输出
|
||||
return typeVariable;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得泛型变量对应的泛型实际类型,如果此变量没有对应的实际类型,返回null
|
||||
* 此方法可以处理
|
||||
*
|
||||
* @param type 类
|
||||
* @param parameterizedType 泛型变量,例如List<T>等
|
||||
* @return 实际类型,可能为Class等
|
||||
*/
|
||||
public static Type getActualType(Type type, ParameterizedType parameterizedType) {
|
||||
// 字段类型为泛型参数类型,解析对应泛型类型为真实类型,类似于List<T> a
|
||||
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
|
||||
|
||||
// 泛型对象中含有未被转换的泛型变量
|
||||
if (TypeUtil.hasTypeVeriable(actualTypeArguments)) {
|
||||
actualTypeArguments = getActualTypes(type , parameterizedType.getActualTypeArguments());
|
||||
if (ArrayUtil.isNotEmpty(actualTypeArguments)) {
|
||||
// 替换泛型变量为实际类型,例如List<T>变为List<String>
|
||||
parameterizedType = new ParameterizedTypeImpl(actualTypeArguments, parameterizedType.getOwnerType(), parameterizedType.getRawType());
|
||||
}
|
||||
}
|
||||
|
||||
return parameterizedType;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得泛型变量对应的泛型实际类型,如果此变量没有对应的实际类型,返回null
|
||||
*
|
||||
* @param type 类
|
||||
* @param typeVariables 泛型变量数组,例如T等
|
||||
* @return 实际类型数组,可能为Class等
|
||||
*/
|
||||
public static Type[] getActualTypes(Type type, Type... typeVariables) {
|
||||
return ActualTypeMapperPool.getActualTypes(type, typeVariables);
|
||||
}
|
||||
}
|
||||
|
@ -446,4 +446,28 @@ public class BeanUtilTest {
|
||||
BeanUtil.setProperty(resultMap, "codeList[0].name", "张三");
|
||||
Console.log(resultMap);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void beanCopyTest(){
|
||||
final Station station = new Station();
|
||||
station.setId(123456L);
|
||||
|
||||
final Station station2 = new Station();
|
||||
|
||||
BeanUtil.copyProperties(station, station2);
|
||||
Assert.assertEquals(new Long(123456L), station2.getId());
|
||||
}
|
||||
|
||||
public static class Station extends Tree<Station, Long> {
|
||||
|
||||
}
|
||||
|
||||
public static class Tree<E, T> extends Entity<T> {
|
||||
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class Entity<T>{
|
||||
private T id;
|
||||
}
|
||||
}
|
||||
|
@ -60,24 +60,23 @@ public class TypeUtilTest {
|
||||
|
||||
@Test
|
||||
public void getActualTypesTest(){
|
||||
final Type idType = TypeUtil.getActualType(
|
||||
Station.class,
|
||||
Tree.class,
|
||||
TypeUtil.getFieldType(Station.class, "id"));
|
||||
// 测试多层级泛型参数是否能获取成功
|
||||
Type idType = TypeUtil.getActualType(Level3.class,
|
||||
ReflectUtil.getField(Level3.class, "id"));
|
||||
|
||||
Assert.assertEquals(Long.class, idType);
|
||||
}
|
||||
|
||||
public static class Station extends Tree<Station, Long>{
|
||||
public static class Level3 extends Level2<Level3>{
|
||||
|
||||
}
|
||||
|
||||
public static class Tree<E, T> extends Entity<T>{
|
||||
public static class Level2<E> extends Level1<Long>{
|
||||
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class Entity<T>{
|
||||
public static class Level1<T>{
|
||||
private T id;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user