Java:如何从泛型类型中获取类文字?

问题

通常情况下,我看到人们像这样使用类文字:

Class<Foo> cls = Foo.class;

但是,如果类型是通用的,例如,名单?这工作正常,但有一个警告,因为List应该参数化:

Class<List> cls = List.class

那么为什么不添加a<?>?好吧,这会导致类型不匹配错误:

Class<List<?>> cls = List.class

我认为这样的东西会起作用,但这只是一个简单的'语法错误:

Class<List<Foo>> cls = List<Foo>.class

我怎样才能得到aClass<List<Foo>>,例如使用类文字?

Icoulduse@SuppressWarnings("unchecked")摆脱了第一个例子Class<List> cls = List.class中非参数化使用List引起的警告,但我宁愿不这样做。

有什么建议么?


#1 热门回答(126 赞)

你不能因为866863286。

Java泛型仅仅是Object强制转换的语法糖。展示:

List<Integer> list1 = new ArrayList<Integer>();
List<String> list2 = (List<String>)list1;
list2.add("foo"); // perfectly legal

在运行时保留泛型类型信息的唯一实例是withField.getGenericType()if通过反射询问类的成员。

所有这一切都是为什么Object.getClass()有这个签名:

public final native Class<?> getClass();

重要的部分是Class<?>

换句话说,从Java Generics FAQ

为什么没有具体参数化类型的类文字?因为参数化类型没有确切的运行时类型表示。类文字表示表示给定类型的Class对象。例如,类文字String.class表示表示String类型的Class对象,与在String对象上调用方法getClass时返回的Class对象相同。类文字可用于运行时类型检查和反射。参数化类型在编译期间在称为类型擦除的过程中转换为字节代码时会丢失其类型参数。作为类型擦除的副作用,泛型类型的所有实例化共享相同的运行时表示,即相应原始类型的表示。换句话说,参数化类型没有自己的类型表示。因此,没有必要形成类文字,例如List <String> .class,List <Long> .class和List <?>。class,因为不存在这样的Class对象。只有原始类型List有一个表示其运行时类型的Class对象。它被称为List.class。


#2 热门回答(45 赞)

参数化类型没有类文字,但是有正确定义这些类型的Type对象。

请参见java.lang.reflect.ParameterizedType -http://java.sun.com/j2se/1.5.0/docs/api/java/lang/reflect/ParameterizedType.html

Google的Gson库定义了一个TypeToken类,它允许简单地生成参数化类型,并使用它以通用友好的方式对具有复杂参数化类型的json对象进行规范。在你的示例中,你将使用:

Type typeOfListOfFoo = new TypeToken<List<Foo>>(){}.getType()

我打算发布到TypeToken和Gson类javadoc的链接,但Stack Overflow不允许我发布多个链接,因为我是新用户,你可以使用Google搜索轻松找到它们


#3 热门回答(41 赞)

你可以用双重角色来管理它:
@SuppressWarnings("unchecked") Class<List<Foo>> cls = (Class<List<Foo>>)(Object)List.class