考虑一段代码:
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 的存在,它被打破了。
是的,我知道在运行时类型参数信息被删除,所以没有类型参数这段代码是完全有效的。我也知道我可以通过指定 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
);由于删除和反射等);但令人高兴的是,正如您所指出的,您的情况似乎不是其中之一。
关于java - 泛型混淆 : deceiving the compiler,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26129973/