使用反射在运行时推断java泛型参数 [英] Inferring java generics parameters at runtime using reflection
问题描述
//将一个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:
- getTypeArguments() from http://www.artima.com/weblogs/viewpost.jsp?thread=208860
- getActualTypeArguments() from https://code.google.com/p/aphillips/source/browse/commons-lang/trunk/src/main/java/com/qrmedia/commons/lang/ClassUtils.java
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屋!