在下面的代码中,我在第5行得到了一个运行时异常,而不是在第4行。演员们到底在做什么?任何见解或相关阅读链接都会很棒。
List list = new LinkedList();
list.add(new Date());
list.add("Hello");
List<String> list2 = (List<String>)list;
String value = list2.get(1);
演员们到底在做什么?
什么都没有,在执行时。这就是为什么你会收到一个警告,说它是一个未检查的强制转换——它实际上并没有检查任何东西,因为对象本身(在执行时)没有List<String>
的概念——它只是一个列表。如果你有:
Object x = ...;
List<String> list = (List<String>) x;
那么这将检查CCD_ 2是否引用了某种类型的列表。。。但它不会检查列表的"字符串性"。
不幸的是,Java泛型就是这样工作的:(
编译器在擦除泛型之前对其进行检查。所以类似于:
final List<String> strings = ...
strings.add(new Date());
将在编译时拾取。
一旦检查了泛型,编译器就会擦除它们,这称为类型擦除。所以在执行时泛型是不存在的。
所以,演员阵容:
final List list = new LinkedList();
final List<String> list2 = (List<String>)list;
实际上什么都不做,因为编译器只能检查list
是List
,而不是检查内容。
然而,编译器会在这里警告您缺少类型检查:
unchecked call to add(E) as a member of the raw type java.util.List
unchecked call to add(E) as a member of the raw type java.util.List
unchecked cast
required: java.util.List<java.lang.String>
found: java.util.List
前两个警告与将项目添加到未知类型的List
有关-这是因为您可以执行相反的操作,这将在运行时导致问题:
List<String> strings = new ArrayList<>();
List raw = strings;
第三个警告是关于从List
到List<String>
的不安全转换。
事实上,你甚至可以这样做(尽管我不建议你这样做):
List<String> strings = new ArrayList<>();
List<Date> dates = (List<Date>) (List) strings;