当您尝试将链接列表强制转换为链接列表<string>?</string>时,编译时会发生什么

时间:2014-11-01 08:45:54

标签: java generics casting

在下面,我在第5行得到一个运行时异常,而不是第4行。这个演员实际上在做什么? 任何有关阅读的见解或链接都会很棒。

List list = new LinkedList();
list.add(new Date());
list.add("Hello");
List<String> list2 = (List<String>)list;
String value = list2.get(1);

2 个答案:

答案 0 :(得分:3)

  

演员实际上在做什么?

执行时没什么。这就是为什么你会收到警告说它是未经检查的演员 - 它没有真正检查任何东西,因为对象本身(在执行时) )没有成为List<String>的概念 - 它只是一个列表。如果你有:

Object x = ...;
List<String> list = (List<String>) x;

然后检查x是否指向某些种类的列表......但它不会检查&#34;字符串&#34;列表。

遗憾的是,这是Java泛型的工作方式:(

答案 1 :(得分:2)

编译器在擦除之前检查泛型。如下所示:

final List<String> strings = ...
strings.add(new Date());

将在编译时获取。

检查泛型后,编译器会删除它们,这称为type erasure。因此,在执行时,泛型不存在。

所以,演员:

final List list = new LinkedList();
final List<String> list2 = (List<String>)list;

实际上 nothing ,因为编译器只能检查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;