使用reflection在运行时推断javagenerics参数
我有一个带有以下签名的方法:
// 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 List getListFromJson( String json, Class itemType, List defValue ) { final ArrayList list = new ArrayList(); 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; }
它读取json字符串并将其转换为适当类型对象的列表,例如。 整数,字符串等
有没有一种强大的方法可以通过从List
参数推断出它来从方法中删除Class
List
参数? 例如。 有没有办法可以在不丢失function的情况下将方法签名更改为以下内容?
public List getListFromJson( String json, List defValue ) { ... }
似乎解决方案需要对ParameterizedType进行一些奇特的操作。 我看过以下内容,但要么我使用这些方法不正确,要么他们没有做我期望的事情:
- 来自http://www.artima.com/weblogs/viewpost.jsp?thread=208860的 getTypeArguments()
- 来自https://code.google.com/p/aphillips/source/browse/commons-lang/trunk/src/main/java/com/qrmedia/commons/lang/ClassUtils.java的 getActualTypeArguments()
由于类型擦除 ,你绝对不能“推断” T
是什么 – 它甚至不存在于运行时。 你最接近的是检查defValue
的值(如果它有值)并获取那里的元素类。
Class> tType = defValue.get(0).getClass(); if (Boolean.class.isAssignableFrom(tType)) { //...
编辑
关于你使用getTypeArguments()
等reflection的想法,那些只提供声明类型的数据,而不是实际类型。 因此,例如,如果您获得了Method
对象的句柄并调用了getTypeParameters()
,那么您只需获取一个包含表示T
的类型对象的数组 – 而不是T
在某些特定运行时调用时所代表的实际类型。
我知道保证在运行时访问该类型的唯一方法是使它成为对象构造函数的参数:
class MyClass { private final Class clazz; public MyClass(Class clazz) { this.clazz=clazz; } }
然后,在实例化对象时必须传递该类:
MyClass object = new MyClass (String.class);
显然,在你的情况下,你有一个有效的静态实用方法,没有对象,所以我认为你坚持使用Class参数或者某种模板对象。