2

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

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

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

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

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

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

4

5 回答 5

1

运行时class字段值不依赖于你应用的泛型类型,这种语法是非法的。更多关于这个here

于 2012-12-05T19:46:17.010 回答
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您应该使用TypeTokenSean Patrick Floyd 提到的技术。

于 2012-12-07T22:00:12.570 回答
0

Type Erasure 抬起了丑陋的脑袋。本质上,Java 对通用<…&gt;子句进行编译时检查,然后将它们从运行时对象中删除,从而永远丢失信息。恶心,嗯?由于.class元对象在运行时被引用,它们也遭受擦除。

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

如果你想要泛型的类型安全,你必须传入两个参数,例如

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

于 2012-12-07T22:20:39.113 回答
0

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

ArrayList list = foot(ArrayList.class)
于 2012-12-05T19:47:32.643 回答
0

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

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

或者

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

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

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

于 2012-12-05T22:43:17.203 回答