使用反射在运行时推断java泛型参数

emm*_*mby 4 java generics reflection

我有一个带有以下签名的方法:

// 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;
}
Run Code Online (Sandbox Code Playgroud)

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

有没有一种强大Class<T>的方法可以通过从List<T>参数中推断出来从方法中删除参数?例如.有没有办法可以在不丢失功能的情况下将方法签名更改为以下内容?

public <T> List<T> getListFromJson( String json, List<T> defValue ) {
    ...
}
Run Code Online (Sandbox Code Playgroud)

似乎解决方案需要对ParameterizedType进行一些奇特的操作.我看过以下内容,但要么我使用这些方法不正确,要么他们没有做我期望的事情:

Mar*_*ers 7

由于类型擦除,你绝对不能"推断" T它是什么- 它甚至不存在于运行时.你最接近的是检查中的值defValue(如果它有值)并获得那里的元素类.

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

if (Boolean.class.isAssignableFrom(tType)) { //...  
Run Code Online (Sandbox Code Playgroud)

编辑

关于你使用反射等的想法getTypeArguments(),那些只提供声明类型的数据,而不是实际类型.因此,例如,如果您获得了Method对象的句柄并进行了调用getTypeParameters(),那么您只需获取一个包含类型对象的数组,该类型对象表示 - T而不是T在某些特定运行时调用时表示的实际类型.