在通配符泛型类型和泛型类型之间取消选中

时间:2015-02-19 16:37:56

标签: java generics unchecked

请帮助我理解为什么这个演员阵容未经检查:

 List<? extends String> t= ...;
 List<String> t2=(List<String>)t;

它应该是完全安全的...... 我想这可能已经被问到了,但是我找不到它......关于泛型的问题太多了!我经常使用仿制药,但这种怀疑一直存在......提前谢谢你。

编辑: 正如所指出的,我应该使用非最终类。 所以:

List<? extends ConfigurationAdapter> t= new ArrayList<DATASOURCE_ConfigurationAdapter>();
List<ConfigurationAdapter> t2=(List<ConfigurationAdapter>)t;

这很有效。我无法理解为什么它没有被检查。

2 个答案:

答案 0 :(得分:3)

我想一个例子可以解释警告的原因。

但是让我们使用其他类型,因为字符串在Java中实际上不具有子类型。

List<Integer> integers = new ArrayList<>(asList(1,2,3,4,5));
List<? extends Number> anyNumbers = integers;

现在,假设我们强制你正在做的演员,想象你甚至可以在没有警告的情况下进行演绎

List<Number> numbers = (List<Number>) anyNumbers;

现在,您可以这样做:

numbers.add(3.5);

后来,在代码中的其他地方,有人试图像这样使用原始集合:

for(Integer myInt: integers) { //ClassCastException

}

你得到一个ClassCastException,因为你现在已经破坏了类型系统的期望。原始集合应该只接受整数,但你已经设法欺骗Java使其接受任何类型的数字,在这种情况下是双重的。当然,当你遍历原始集合时,期望整数,当你找到一个实际上不是整数的整数时,你的代码就会失败。

这就是编译器抛出警告是合乎逻辑的原因,这就是为什么不听它的危险。事实上,String是Java中的最终类,这就是为什么在你的特定情况下你可能找不到任何完成我刚刚描述的这个问题的场景的原因。但对于其他情况,这可能是可能的。

答案 1 :(得分:2)

对于String,它是完全安全的,你可以忽略警告。对于类型为final class类型的任何类型绑定,情况也是如此。

对于任何其他类型,分配给t的值的类型可能是List<SubtypeOfTheBound>。在这种情况下,无法将其分配给List<Bound>

更多阅读: