考虑一个代码:
public class GenericsConfusion {
public static <T> Class<T> get(Class<T> clazz) {
Map<Class, Class> map = new HashMap<Class, Class>();
map.put(Integer.class, String.class);
return map.get(clazz);
}
public static void main(String[] args) {
Class<Integer> clazz = get(Integer.class);
System.out.println(clazz);
}
}
它可以编译并完美运行。想法是在get方法中返回与输入类具有相同类型参数的类。但是由于地图的存在,它被打破了。是的,我知道在运行时会删除类型参数信息,因此,如果没有类型参数,此代码将完全有效。我也知道可以通过指定来修复它,Map<Class<T>, Class<T>>
但是事实是,在方法签名中,我具有类型参数,并且它们在编译时没有帮助。
这是对某些概念的滥用吗?
还是Java泛型的缺点?
还是完全正常,我误解了类型参数的概念?
甲原始类型,如Class
或Map
(相对于Class<...>
或Map<..., ...>
),绕过泛型的检查类型。您甚至可以编写如下内容:
final Class<Integer> whoops = (Class) String.class;
这是类型系统中的一个不幸的弱点。它最初包含在Java 5中(引入了泛型)是为了与以前版本下编写的代码兼容。
在大多数情况下,可以通过避免使用原始类型来避免此缺点。您的编译器应警告您有关它们的信息。
不幸的是,在很多情况下原始类型是不可避免的(由于的特殊类型.getClass()
;由于我们只能写(例如)Map.class
而不能Map<String, String>.class
(或Map.<String, String>class
);由于擦除和反射等原因);但是很高兴,正如您所指出的,您的情况似乎并非其中之一。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句