【发布时间】:2016-10-15 20:32:19
【问题描述】:
所以,假设我有一个简单的列表,如果整数:
List<Integer> intList = new ArrayList<>();
intList.add(1);
intList.add(2);
// intList.add("zxc"); // this will obviously fail
现在让我们将列表包装在另一个列表中:
List<List<Integer>> listOfListOfInt = new ArrayList<>();
listOfListOfInt.add(intList);
一切都好。现在让我们创建方法
private static void method1(List<? extends List> cont) { // [1]
List<? super Date> data = cont.get(0); // [2]
data.add(new Date());
}
基本上我将 DATE 添加到列表中的第一个列表,因为我告诉它将该列表视为List<? super Date>。
当然,由于类型擦除,它可以工作:
method1(listOfListOfInt);
System.out.println(intList);
打印[1, 2, Tue Jun 14 23:41:15 BST 2016],所以我的List<Integer> 现在有一个日期。
现在我明白了发生了什么,因为类型擦除 List<? extends List> 变成了一个列表,然后由我决定在其中放入什么,所以我要放入日期。
现在我不太明白的问题是,为什么根本没有“未经检查的分配/调用”的警告?根据 java 编译器,代码是完全类型安全的?
如果在方法 1 中您将 List<? extends List> 替换为 List<List>,或者如果您将 List<? super Date> 替换为 List 等等,它将给出警告,通常您'将收到有关未经检查的分配/调用的警告。但在这种情况下你不会,一切都很好。
更新:显然编译器有警告,但 Intellij Idea 出于某种原因拒绝显示它。我设置了“未经检查的警告”检查,没有忽略任何内容。我认为所有设置都是默认设置。
IntelliJ IDEA 2016.1.3 Build #IC-145.1617,构建于 2016 年 6 月 3 日 JRE: 1.8.0_77-b03 x86 JVM:Oracle Corporation 的 Java HotSpot(TM) Server VM
Update2:它不是重复的,因为问题不在于原始类型的功能,而在于在这种特殊情况下缺乏警告。事实证明这只是一个 IDE 怪癖。
【问题讨论】:
-
我收到警告。你如何编译你的代码?
-
这与向后兼容性有关,而不是与擦除有关。为什么很容易将所有事情都归咎于擦除?
-
您的问题是
List<? extends List>类型中的第二个List是raw。 Raw 与 erasure 不同。 Raw 会失去类型安全性,而擦除不会。你的 IDE(!) 应该已经警告你关于泛型的原始使用。 -
我不是在“责备”类型擦除,它按预期工作。我只是对这种情况下没有警告感到困惑。
-
那么我将泛型类型转换为原始类型的警告在哪里呢?请注意,如果您使用稍微不同的 RAW 类型
<List<List>>而不是List<? extends List>,则会发出警告。
标签: java generics type-conversion