Java将参数化泛型类型作为valueType发送

时间:2012-12-05 19:41:37

标签: java generics

我有一个返回给定类型的方法:

T foo(Class<T> valueType) {...};

String s = foo(Java.lang.String.class);

我正在尝试将泛型类型作为我的类发送,但是会出现编译器错误。例如,假设我想返回一个字符串的ArrayList:

ArrayList<String> list = foot(ArrayList<String>.class)

参数“String”给出错误。无论如何我可以指定要返回的泛型类型吗?

5 个答案:

答案 0 :(得分:1)

运行时class字段值不依赖于您应用的泛型类型,并且此语法是非法的。有关here的更多信息。

答案 1 :(得分:0)

这对你有用(编辑过)吗?

ArrayList list = foot(ArrayList.class)

答案 2 :(得分:0)

只需转换方法的输入或输出:

ArrayList<String> list = foot((Class<ArrayList<String>>)(Class<?>)ArrayList.class);

ArrayList<String> list = (ArrayList<String>)foot(ArrayList.class);

基本上,Class类与泛型不兼容,因为它表示运行时事物,而泛型在编译时工作。在运行时,程序中只有ArrayList的一个类对象。即使您将其称为Class<ArrayList<String>>Class<ArrayList<Integer>>Class<ArrayList>,它仍然是同一个对象。那应该是什么类型的?没有简单的答案适用于所有事情。

Java语言决定类文字ArrayList.class应该只有Class<ArrayList>类型。但是当你想要一个Class<ArrayList<String>>类型的表达式时,这会导致问题,所以你必须弯曲类型。

答案 3 :(得分:0)

假设您只关心静态类型,这个技巧可能会有用:

@SuppressWarnings("unchecked")
public static <T>
Class<T> appropriateClass(T... args) {
    return (Class<T>) args.getClass().getComponentType();
}

Class<ArrayList<String>> c = appropriateClass();
ArrayList<String> list = foo(c);

其实我并不为这个伎俩感到骄傲。但你可能想尝试一下。

如果你测试它:

System.out.println(c); // prints "class java.util.ArrayList"

所以它等同于像(Class<ArrayList<String>>) (Class<?>) ArrayList.class这样丑陋的演员。

如果您确实需要在运行时为ArrayList<String>ArrayList添加不同的令牌,则应使用Sean Patrick Floyd提到的TypeToken技术。

答案 4 :(得分:0)

类型Erasure看起来很难看。从本质上讲,Java会对通用<…>子句进行编译时检查,然后从运行时对象中删除,永远丢失信息。讨厌,嗯?由于.class元对象在运行时被引用,因此它们也会遭受擦除。

ArrayList<String>.class在编译时被删除,为ArrayList.class

如果您希望使用泛型类型安全,则必须传入两个参数,例如

ArrayList<String> foo = foot(ArrayList.class, String.class)

相关问题