使用反射在运行时推断java泛型参数 [英] Inferring java generics parameters at runtime using reflection

查看:122
本文介绍了使用反射在运行时推断java泛型参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

  //将一个json字符串转换为一个对象列表
//假设:json是一个数组,并且列表中的所有项都是相同的类型
public< T>列表与LT; T> getListFromJson(String json,Class< T> itemType,List< T> defValue){
final ArrayList< T> list = new ArrayList< T>(); $())
$ b $(b) .getAsNumber():
Boolean.class.isAssignableFrom(itemType)?e.getAsBoolean():
Character.class.isAssignableFrom(itemType)?e.getAsCharacter():
String.class .isAssignableFrom(itemType)?e.getAsString():
JsonElement.class.isAssignableFrom(itemType)?e:
null

);

返回列表;
}

它读取json字符串并将其转换为适当类型的列表对象,例如。整数,字符串等。

是否有强大的方法从方法中移除 Class< T> 参数通过从 List< T> 参数推断它?例如。有没有一种方法可以将方法签名更改为以下方式而不会丢失功能?

  public< T>列表与LT; T> getListFromJson(String json,List< T> defValue){
...
}



看起来解决方案将需要对ParameterizedType进行一些奇妙的操作。我已经看了下面的内容,但是我不正确地使用这些方法,或者他们没有做我期望的:


解决方案

由于输入删除,您绝对不能推断什么 T 是 - 它在运行时甚至不存在。您可以最接近的是检查 defValue 中的值(如果它有值)并获取元素的类。

  Class<?> tType = defValue.get(0).getClass(); 

if(Boolean.class.isAssignableFrom(tType)){// ...



Edit



关于您使用像 getTypeArguments()等反射的思考,为声明的类型提供数据,而不是实际的类型。例如,如果您获得了 Method 对象的句柄并调用 getTypeParameters(),那么您只需获取一个包含表示 T 的类型对象的数组 - 不是 T 在某些特定运行时调用时表示的实际类型。 / p>

I have a method with the following signature:

// Converts a json string to a list of objects
// Assumption: json is an array, and all items in the list are of the same type
public <T> List<T> getListFromJson( String json, Class<T> itemType, List<T> defValue ) {
    final ArrayList<T> list = new ArrayList<T>();

    for( JsonElement e : parser.parse(json).getAsJsonArray())
        list.add( (T) (
                Number.class.isAssignableFrom(itemType) ? e.getAsNumber() :
                Boolean.class.isAssignableFrom(itemType) ? e.getAsBoolean() :
                Character.class.isAssignableFrom(itemType) ? e.getAsCharacter() :
                String.class.isAssignableFrom(itemType) ? e.getAsString() :
                JsonElement.class.isAssignableFrom(itemType) ? e :
                null
            )
        );

    return list;
}

It reads the json string and converts it to a list of the appropriate type of object, eg. Integer, String, etc.

Is there a robust way to remove the Class<T> argument from the method by inferring it from the List<T> parameter? Eg. Is there a way I can change the method signature to the following without losing functionality?

public <T> List<T> getListFromJson( String json, List<T> defValue ) {
    ...
}

It seems like the solution is going to require some fancy manipulation of ParameterizedType. I've looked at the following, but either I'm using these methods incorrectly or they're not doing what I expect:

解决方案

Due to type erasure, you definitely can't "infer" what T is--it doesn't even exist at runtime. The closest you could come is inspect the values in defValue (if it has values) and get the class of the elements there.

Class<?> tType = defValue.get(0).getClass();

if (Boolean.class.isAssignableFrom(tType)) { //...  

Edit

With regards to your thinking of using reflection like getTypeArguments(), etc. Those only provide data for declared types, never actual types. So for example, if you got a handle to the Method object and called getTypeParameters(), you'd just get an array containing a type object representing T--not the actual type that T represents at some specific runtime invocation.

这篇关于使用反射在运行时推断java泛型参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆