当您尝试将 LinkedList 转换为 LinkedList 时,在编译时会发生什么<String>情况?



在下面的代码中,我在第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;

实际上什么都不做,因为编译器只能检查listList,而不是检查内容。

然而,编译器会在这里警告您缺少类型检查:

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;

第三个警告是关于从ListList<String>的不安全转换。

事实上,你甚至可以这样做(尽管我不建议你这样做):

List<String> strings = new ArrayList<>();
List<Date> dates = (List<Date>) (List) strings;

最新更新