简体   繁体   English

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

[英]Unchecked cast between wildcard generic type and generic type

please help me to understand why this cast is unchecked: 请帮助我了解为什么未选中此演员表:

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

It should be totally safe... I think this has probably already been asked, but I can't find it... too many questions about generics! 应该是完全安全的……我想可能已经有人问过了,但是我找不到它……关于泛型的太多问题! I use regularly generics, but this doubt has always been there... Thank you in advance. 我经常使用泛型,但是这个疑问一直存在……谢谢。

Edit: As pointed out, I should have used a non final class. 编辑:如前所述,我应该使用非最终课程。 So: 所以:

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

This works. 这可行。 I can't understand why it's unchecked. 我不明白为什么它没有被选中。

I suppose an example can explain the reason of the warning. 我想一个例子可以解释警告的原因。

But let's use other type, since strings cannot actually have subtypes in Java. 但是,让我们使用其他类型,因为在Java中字符串实际上不能具有子类型。

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

Now, suppose we force the cast that you are doing, imagine that you could even do it without a warning 现在,假设我们强制执行您正在执行的演员表,想象您甚至可以在没有警告的情况下进行

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

Now, you could do this: 现在,您可以执行以下操作:

numbers.add(3.5);

And later, in some other place in your code, somebody is trying to use the original collection like this: 后来,在代码的其他位置,有人试图使用原始集合,如下所示:

for(Integer myInt: integers) { //ClassCastException

}

You get a ClassCastException because you have now broken the expectations of the type system. 之所以收到ClassCastException,是因为您现在违反了类型系统的期望。 The original collection should accept Integers only, but you have managed to fool Java to make it accept any kind of numbers, in this case a double. 原始集合只应接受Integers,但是您设法使Java欺骗以使其接受任何类型的数字,在这种情况下为双精度。 Of course, when you iterate over the original collection, expecting integers, when you find one that is not actually an integer, your code will fail. 当然,当您遍历原始集合并期望使用整数时,如果发现实际上不是整数的代码,则代码将失败。

That's why it is logical that the compiler throws a warning, and that's why it is dangerous not to listen to it. 因此,编译器发出警告是合乎逻辑的,这就是为什么不听警告很危险。 And the fact that the String is a final class in Java is the reason why in your particular case you won't probably find any scenarios that finish in this problem I just described. 而且String是Java中的最终类这一事实是为什么在您的特殊情况下您可能找不到我刚刚描述的解决此问题的任何方案的原因。 But for other cases, this is a likely possibility. 但是对于其他情况,这是可能的。

For String it is totally safe and you can ignore the warning. 对于String来说,它是完全安全的,您可以忽略警告。 The same would go for any type bound where the type is a final class type. 对于类型为final class类型的任何类型绑定,也是如此。

For any other type, the type of the value assigned to t might be a List<SubtypeOfTheBound> . 对于任何其他类型,分配给t的值的类型可能是List<SubtypeOfTheBound> In which case, it could not be assigned to a List<Bound> . 在这种情况下,无法将其分配给List<Bound>

More reading: 更多阅读:

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM