在Java中将类型参数的类作为类型参数传递给泛型方法
问题摘要:我想将类型参数(例如ArrayList<SomeClass>
)的类作为类型参数传递给泛型方法。
假设我有一个方法:
public static <T> T getGenericObjectFromJson(String json, Class<T> genericType){
// details unimportant, basically returns an object of specified type
return JsonParser.fromJson(json, genericType);
}
当然,这种方法对于任何一类课程都可以很好地工作。 我可以这样调用方法,例如:
getGenericObjectFromJson(jsonString, User.class)
问题:我发现我不能这样做:
getGenericObjectFromJson(jsonString, ArrayList<User>.class)
在语法上,这显然是无效的。 但是,我不确定我会如何完成这样的事情。 当然,我可以传递ArrayList.class
,但是通用类型的添加使得它不再是语法上有效的,我想不出一种解决方法。
唯一的直接解决方案是这样的(这看起来相当愚蠢):
getGenericObjectFromJson(jsonString, new ArrayList<User>().getClass())
然而,我们最终失去了泛型类型,只是返回一个未知类型的ArrayList(尽管它可以被强制转换)。 另外,不必要地实例化一个对象。
到目前为止,我唯一的解决方案是将该方法包装在一个包含可以实例化的泛型类型参数的类中,如下所示:
public class JsonDeserializer<T>...
在这种情况下, getGenericObjectFromJson
方法将使用该类的泛型类型。
问题:最后,我很好奇为什么我不能通过类型参数的类,以及是否有办法完成我尝试做的事情。
一如往常,让我知道这个问题是否有问题。
这实际上可能在Java中使用一些“技巧”。 不要屈服于C#狂热者的压力! (J / K)
“技巧”是创建一个扩展泛型类型的类,并通过.getGenericSuperclass()
或.getGenericInterfaces()
返回的Type
来.getGenericSuperclass()
父类的类型参数的值。
这非常麻烦。 为了简化我们的生活,Google已经为我们编写了大部分代码的无聊部分,并通过Guava提供。
检查TypeToken
类,它完全符合你的要求。 例如:
TypeToken<List<String>> stringListTok = new TypeToken<List<String>>() {};
然后你传递一个TypeToken<T>
而不是Class<T>
,就这些了。 它为您提供了对由T表示的类型进行反射的方法。
它在内部做的只是简单地调用.getClass().getGenericSuperclass()
(或...Interfaces()
),然后将一些丑陋的从Type
转换为ParameterizedType
并从中检索所有信息( .getActualTypeArguments()
等)。
最后,如果你想做类似于依赖注入的事情(也就是说,假设你需要在Class<T>
的构造函数中注入一个Class<T>
,或者你想获得一个实例应该依赖的参数化接口的实例在类型参数上),Google Guice(来自Google的DI容器)有一个非常类似的机制来解决这个问题,称为TypeLiteral
。 幕后的使用和代码几乎与Guava的TypeToken
相同。 在这里检查: TypeLiteral
上一篇: Passing a class with type parameter as type parameter for generic method in Java
下一篇: Why shouldn't Java enum literals be able to have generic type parameters?