通配符泛型类型和泛型类型之间未经检查的转换

Unchecked cast between wildcard generic type and generic type

请帮助我理解为什么这个转换未被选中:

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

应该是绝对安全的... 我认为这可能已经被问过,但我找不到它......关于泛型的问题太多了!我经常使用泛型,但这个疑问一直存在......提前谢谢你。

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

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

这行得通。我不明白为什么它没有被选中。

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

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

更多阅读:

  • Is List<Dog> a subclass of List<Animal>? Why aren't Java's generics implicitly polymorphic?

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

但是让我们使用其他类型,因为字符串在 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 中的最终 class 这一事实是为什么在您的特定情况下您可能找不到任何解决我刚才描述的问题的场景的原因。但对于其他情况,这是一个可能的可能性。