考虑一下代码:
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);
}
}
Run Code Online (Sandbox Code Playgroud)
它编译和运行完美.我们的想法是在get方法中返回与输入类具有相同类型参数的类.但由于地图的存在,它被打破了.是的,我知道在运行时会删除类型参数信息,因此如果没有类型参数,则此代码完全有效.另外我知道我可以通过指定修复它Map<Class<T>, Class<T>>但事实是在方法签名中我有类型参数,并且它们在编译时没有帮助我.
这是滥用某些概念吗?
或者它是Java泛型的缺点?
或者它完全可以,我误解了类型参数的想法?
甲原始类型,如Class或Map(相对于Class<...>或Map<..., ...>),绕过泛型的类型检查.你甚至可以写这样的东西:
final Class<Integer> whoops = (Class) String.class;
Run Code Online (Sandbox Code Playgroud)
这是类型系统中一个令人遗憾的弱点.它最初包含在Java 5(引入泛型)中,以便与先前版本中编写的代码兼容.
在大多数情况下,您可以通过避免使用原始类型来避免这种弱点.您的编译器应该警告您.
不幸的是,在各种情况下,原始类型基本上是不可避免的(由于特殊的类型.getClass();由于我们只能写(例如)Map.class而不能Map<String, String>.class(或Map.<String, String>class);由于擦除和反射等原因;); 但幸运的是,正如你所指出的,你的情况似乎并不是其中之一.
| 归档时间: |
|
| 查看次数: |
1203 次 |
| 最近记录: |