当前位置: 首页 > 面试题库 >

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

万俟铭
2023-03-14
问题内容

问题摘要: 我想将具有类型参数(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)

“技巧”是创建一个扩展通用类型的类,并Type通过.getGenericSuperclass()或返回的值访问父类的类型参数的值.getGenericInterfaces()

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

检查 TypeToken 课程,它确实满足您的要求。例如:

TypeToken<List<String>> stringListTok = new TypeToken<List<String>>() {};

然后,您绕过a TypeToken<T>而不是a就Class<T>这样。它为您提供了对T表示的类型进行反射的方法。

它在内部所做的只是调用.getClass().getGenericSuperclass()(或...Interfaces()),然后从Type进行一些丑陋的转换,ParameterizedType并从那里检索所有信息(.getActualTypeArguments(),等等)。

最后,如果您想对Dependency Injection做一些类似的事情(即,假设您需要Class<T>在类的构造函数中注入a
,或者想获取某个参数化接口的实例,则该实例中的实例应取决于类型参数) ),Google
Guice(来自Google的DI容器)具有一种非常相似的机制来解决该问题,称为TypeLiteral。幕后的用法和代码与TypeTokenGuava
几乎相同。在这里检查: TypeLiteral




 类似资料:
  • 问题总结:我想传递一个带有类型参数(如

  • 我写了以下方法 我如何将不同的枚举类型传递给第二个参数?我知道我不能创建枚举的实例,但初始化枚举意味着我将传递一个值,而不是整个初始化的枚举,如下所示...其他枚举也将传递给相同的方法以实现组合细节

  • 问题内容: 您认为可以创建类似的东西吗? 问题答案: 是的你可以。 用法示例:

  • 所以我试着做下面这样的事情 并且定义为 当尝试编译代码时,clang给出错误。我发现这是因为你不能从lambda推断出类型。 所以这实际上是正确的,因为我实际上希望的参数类型是从的参数推导出的类型。 所以我的问题是,有没有可能排除参数的推导,而只是使用的推导类型?

  • 问题内容: 我有一个方法以a 作为参数。 在中,我如何知道a 是还是a 是? 问题答案: 根据用户omain的回答“如果使用<?>,则意味着您将不会在任何地方使用参数化类型。要么转到特定类型(在您的情况下,似乎是),要么转到非常通用的“ 另外,我相信如果您使用问号,编译器将在运行时(类型;有效Java的第119页)消除类型不匹配的情况,绕过擦除,并有效地消除了使用泛型类型所带来的好处? 要回答发问

  • 我想使用泛型类作为另一个泛型类的类型参数。 起初,我对类的定义是这样的: 然后我的需求发生了变化,我不得不为我的R类型使用包装器/持有者类 到目前为止,我的尝试:(给出编译时错误: