将类型参数的类作为Java中泛型方法的类型参数传递

Pau*_*ter 52 java generics class

问题摘要: 我想将类型参数(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); 
    }
Run Code Online (Sandbox Code Playgroud)

当然,这种方法对于任何类别都可以完美地运行.我可以像这样调用方法,例如:

getGenericObjectFromJson(jsonString, User.class)
Run Code Online (Sandbox Code Playgroud)

问题:我发现我不能这样做:

getGenericObjectFromJson(jsonString, ArrayList<User>.class)
Run Code Online (Sandbox Code Playgroud)

从语法上讲,这显然是无效的.但是,我不确定我是如何做到这样的.当然,我可以通过ArrayList.class,但是通用类型的添加使它不再具有语法上的有效性,我无法想到解决它的方法.

唯一直接的解决方案就是这样(看起来很傻):

getGenericObjectFromJson(jsonString, new ArrayList<User>().getClass())
Run Code Online (Sandbox Code Playgroud)

但是我们最终会丢失泛型类型,并且只返回一个未知类型的ArrayList(尽管它可以被强制转换).另外,不必要地实例化对象.

到目前为止,我唯一的解决方案是将该方法包装在一个包含可以实例化的泛型类型参数的类中,如下所示:

public class JsonDeserializer<T>...
Run Code Online (Sandbox Code Playgroud)

在这种情况下,该getGenericObjectFromJson方法将使用类的泛型类型.

问题:最后,我很好奇为什么我不能传递一个带有类型参数的类,以及是否有办法完成我试图做的事情.

一如既往,请告诉我这个问题是否有任何问题.

Bru*_*eis 60

这实际上可以在Java中使用一些"技巧".不要屈服于C#狂热分子的压力!(J/K)

"技巧"是创建一个扩展泛型类型的类,并通过Type返回的.getGenericSuperclass()or来访问父类的type参数的值.getGenericInterfaces().

这非常麻烦.为了简化我们的生活,Google已经为我们编写了大部分无聊的代码部分,并通过Guava提供.

检查TypeToken课程,这完全符合你的要求.例如:

TypeToken<List<String>> stringListTok = new TypeToken<List<String>>() {};
Run Code Online (Sandbox Code Playgroud)

然后你绕过一个TypeToken<T>而不是一个,Class<T>而这就是全部.它为您提供了对T表示的类型进行反射的方法.

什么这是内部做的是简单地调用.getClass().getGenericSuperclass()(或...Interfaces()),然后从一些丑陋的铸件TypeParameterizedType,并从那里获取的所有信息(.getActualTypeArguments()等).

最后,如果你想用Dependency Injection做类似的事情(也就是说,假设你需要Class<T>在类的构造函数上注入一个,或者你想获得一个参数化接口的实例,其中实例应该依赖于类型参数),谷歌Guice(谷歌的一个DI容器)有一个非常类似的机制来解决这个问题,叫做TypeLiteral.幕后使用和代码几乎与TypeTokenGuava 相同.在这里查看:TypeLiteral