NutzCN Logo
问答 Map转泛型基类字段类型不正确问题
发布于 2706天前 作者 zhwq1216 2403 次浏览 复制 上一个帖子 下一个帖子
标签:

BaseEntity是泛型基类,有个id泛型字段
public class BaseEntity implements Serializable{
private static final long serialVersionUID = -5282762416250405030L;
private T id;
//省略get、set方法和其他属性
}

User类继承自泛型BaseEntity基类
public class User extends BaseEntity implements Serializable {
}

    Map<String, Object> map = new HashMap<String, Object>();
    map.put("id", new Integer(1));

map中id字段放入Integer类型(此处为了测试描述问题,设置为Integer类型),然后使用Lang.map2Object(map, User.class);转化为user对象,获取到的user的id字段没有被转化为期望的Long类型,已经nutz版本是1.r.62。

请问这个问题有办法解决吗?

11 回复

推断不出来这个属性的类型是Long吧?

写错了,应该是继承自BaseEntity

public class User extends BaseEntity<Long> implements Serializable {
}

是报错了还是怎样了?

没有报错,是得到的user对象中id字段不是期望的Long类型,而是Integer类型。

如果再把user对象的id赋给Long类型的字段就会报类型转化错误了

晚上我试试看

试一下, 是报错的

https://github.com/nutzam/nutz/issues/1288

尝试从id这个属性获取类型,始终拿不到Long这个类型

参考fastjson中的获取泛型类中真实类型的代码片段,在org.nutz.lang.reflect.ReflectTool类中增加如下方法:

    /**
     * 泛型类clazz,field字段的真实class对象.
     * @param clazz 泛型class
     * @param field 字段
     * @return
     */
    public static Class<?> getGenericFieldType(Class<?> clazz, Field field) {
        Type fieldType = field.getGenericType();
        return getRealGenericClass(clazz, fieldType);
    }

    /**
     * 获取泛型类中type变量对应的真实class
     * @param clazz 泛型基类.
     * @param type 泛型基类中的某个type
     * @return
     */
    public static Class<?> getRealGenericClass(Class<?> clazz, Type type) {
        if(type instanceof TypeVariable) {
            TypeVariable<?> tv = (TypeVariable<?>) type;
            Type genericFieldType = getInheritGenericType(clazz, tv);
            if (genericFieldType != null) {
                return Lang.getTypeClass(genericFieldType);
            }
        }
        return Lang.getTypeClass(type);
    }

    /**
     * 获取泛型类中type对应的真实Type
     * @param clazz
     * @param type
     * @return
     */
    public static Type getInheritGenericType(Class<?> clazz, Type type) {
        if(type instanceof TypeVariable) {
            TypeVariable<?> tv = (TypeVariable<?>) type;
            return getInheritGenericType(clazz, tv);
        }else {
            return type;
        }
    }

    /**
     * 获取泛型类clazz中某个TypeVariable对应的真实Type.
     * @param clazz
     * @param tv
     * @return
     */
    public static Type getInheritGenericType(Class<?> clazz, TypeVariable<?> tv) {
        Type type = null;
        GenericDeclaration gd = tv.getGenericDeclaration();

        do {
            type = clazz.getGenericSuperclass();
            if (type == null) {
                return null;
            }
            if (type instanceof ParameterizedType) {
                ParameterizedType ptype = (ParameterizedType) type;

                Type rawType = ptype.getRawType();
                boolean eq = gd.equals(rawType) || (gd instanceof Class && rawType instanceof Class && ((Class) gd).isAssignableFrom((Class) rawType));
                if (eq) {
                    TypeVariable<?>[] tvs = gd.getTypeParameters();
                    Type[] types = ptype.getActualTypeArguments();
                    for (int i = 0; i < tvs.length; i++) {
                        if (tv.equals(tvs[i])) {
                            return types[i];
                        }
                    }
                    return null;
                }
            }
            clazz = Lang.getTypeClass(type);
        } while (type != null);
        return null;
    }

然后修改org.nutz.lang.Lang#map2Object方法中的

                //Class<?> ft = field.getType();
                Class<?> ft = ReflectTool.getGenericFieldType(toType, field);

修改org.nutz.lang.inject.InjectBySetter#inject方法

            Type realType = ReflectTool.getInheritGenericType(obj.getClass(), type);
            Class<?> realValuType = Lang.getTypeClass(realType);
            if (isMapCollection && value != null && value instanceof String) {
                v = Json.fromJson(realType, value.toString());
            } else {
                v = Castors.me().castTo(value, realValuType);
            }

这样测试时可以正常设置对应的值

发个pull req嘛

好的。从github上面clone比较慢,2个多小时了还没有检查完成。

git clone --depth=1 https://github.com/你的用户名/nutz

添加回复
请先登陆
回到顶部