通常,我看到人们这样使用类文字:
Class<Foo> cls = Foo.class;
但是如果类型是泛型的,比如List呢?这很好,但有一个警告,因为List应该参数化:
Class<List> cls = List.class
那么为什么不添加一个<?>?这将导致类型不匹配错误:
Class<List<?>> cls = List.class
我想这样做是可行的,但这只是一个简单的语法错误:
Class<List<Foo>> cls = List<Foo>.class
我怎么能得到一个类<列表<Foo>>静态,例如使用类文字?
在第一个例子Class<List> cls = List. Class中,我可以使用@SuppressWarnings(“unchecked”)来消除因非参数化使用List而引起的警告,但我宁愿不这样做。
有什么建议吗?
为了阐明cletus的答案,在运行时删除所有泛型类型的记录。泛型只在编译器中处理,用于提供额外的类型安全。它们实际上只是允许编译器在适当的位置插入类型转换的简写。例如,以前你必须做以下事情:
List x = new ArrayList();
x.add(new SomeClass());
Iterator i = x.iterator();
SomeClass z = (SomeClass) i.next();
就变成了
List<SomeClass> x = new ArrayList<SomeClass>();
x.add(new SomeClass());
Iterator<SomeClass> i = x.iterator();
SomeClass z = i.next();
这允许编译器在编译时检查代码,但在运行时它看起来仍然像第一个示例。
参数化类型没有Class字面量,但是有正确定义这些类型的Type对象。
看到java.lang.reflect.ParameterizedType
——http://java.sun.com/j2se/1.5.0/docs/api/java/lang/reflect/ParameterizedType.html
谷歌的Gson库定义了一个TypeToken类,允许简单地生成参数化类型,并使用它以通用友好的方式规范具有复杂参数化类型的json对象。在你的例子中,你可以用:
Type typeOfListOfFoo = new TypeToken<List<Foo>>(){}.getType()
我打算发布到TypeToken和Gson类javadoc的链接,但堆栈溢出不会让我发布多个链接,因为我是一个新用户,你可以很容易地使用谷歌搜索找到它们
Java泛型常见问题解答和cletus的回答听起来好像Class<List<T>>是没有意义的,但真正的问题是这是极其危险的:
@SuppressWarnings("unchecked")
Class<List<String>> stringListClass = (Class<List<String>>) (Class<?>) List.class;
List<Integer> intList = new ArrayList<>();
intList.add(1);
List<String> stringList = stringListClass.cast(intList);
// Surprise!
String firstElement = stringList.get(0);
cast()使它看起来似乎是安全的,但实际上它一点也不安全。
虽然我不知道哪里不能有List<?>.class = Class<List<?>>,因为当你有一个基于Class参数的泛型类型确定类型的方法时,这将是非常有用的。
对于getClass(), JDK-6184881请求切换到使用通配符,但是看起来不会执行这个更改(很快),因为它与前面的代码不兼容(请参阅注释)。
为了阐明cletus的答案,在运行时删除所有泛型类型的记录。泛型只在编译器中处理,用于提供额外的类型安全。它们实际上只是允许编译器在适当的位置插入类型转换的简写。例如,以前你必须做以下事情:
List x = new ArrayList();
x.add(new SomeClass());
Iterator i = x.iterator();
SomeClass z = (SomeClass) i.next();
就变成了
List<SomeClass> x = new ArrayList<SomeClass>();
x.add(new SomeClass());
Iterator<SomeClass> i = x.iterator();
SomeClass z = i.next();
这允许编译器在编译时检查代码,但在运行时它看起来仍然像第一个示例。
你可以使用一个helper方法来去除整个类中的@SuppressWarnings("unchecked")。
@SuppressWarnings("unchecked")
private static <T> Class<T> generify(Class<?> cls) {
return (Class<T>)cls;
}
然后你可以写
Class<List<Foo>> cls = generify(List.class);
其他用法示例包括
Class<Map<String, Integer>> cls;
cls = generify(Map.class);
cls = TheClass.<Map<String, Integer>>generify(Map.class);
funWithTypeParam(generify(Map.class));
public void funWithTypeParam(Class<Map<String, Integer>> cls) {
}
然而,由于它很少真正有用,而且该方法的使用不利于编译器的类型检查,所以我不建议在它可以公开访问的地方实现它。