Java泛型:无法将List转换为List

9 浏览
0 Comments

Java泛型:无法将List转换为List

刚刚遇到了这个问题:

List a1 = new ArrayList();
List b1 = a1;  // 编译错误:不兼容的类型

其中类型DataNode是Tree的子类型。

public class DataNode implements Tree

令人惊讶的是,对于数组来说,这是可以的:

DataNode[] a2 = new DataNode[0];
Tree[] b2 = a2;   // 这是可以的

这有点奇怪。有人能解释一下吗?

0
0 Comments

Java泛型中无法将List转换为List的问题,是因为Java泛型在设计时考虑到了类型安全性的问题。如果允许这种类型转换,可能会导致类型不匹配的情况发生,破坏了泛型的类型安全性。

假设以下代码是允许的:

List a1 = new ArrayList();
List b1 = a1;  // 假设这是允许的

那么我可以继续执行以下操作:

b1.add(new TreeThatIsntADataNode()); // b1是List,所以这是可以的
for (DataNode dn : a1) {
  // 啊哦!a1中有一些不是DataNode的东西!
}

这样就会导致在遍历a1时出现类型不匹配的情况,违反了泛型的类型安全性。

在理想情况下,当使用只读的变体(variant)的List时,应该允许进行所需的类型转换,但是不允许在使用可读写的接口(如List)时进行类型转换。然而,Java不允许在泛型参数上使用这种variance的注解。即使允许使用,也只能在A和B完全相同的情况下将List转换为List

虽然Java不允许在类的定义中使用此种variance的注解,但是可以使用通配符解决这个问题。可以将变量声明为List类型,这是允许的。

Java泛型不允许将List转换为List是为了保证类型安全性,防止类型不匹配的情况发生。可以使用通配符来解决这个问题。

0
0 Comments

问题的原因是Java中的泛型不支持将List直接赋值给List,这是因为泛型是不可协变的。解决方法是使用通配符和双重转型。

在上述代码中,我们有一个List类型的列表a1,我们想要将其转换为List类型的列表b1。由于泛型的不可协变性,我们不能直接将a1赋值给b1。

为了解决这个问题,我们可以使用通配符和双重转型。首先,我们将a1转换为一个通配符类型的列表,即List,这样就可以将a1赋值给该列表。然后,我们再将该列表强制转型为List类型的列表,即List

下面是解决这个问题的代码示例:

List a1 = new ArrayList();
List b1 = (List) (List) a1;

请注意,这种双重转型的方式是一种不太优雅的方式,因为它绕过了Java泛型的类型检查机制。在进行这种转型时,我们需要确保转换是安全的,即确保a1中的元素类型是Tree或其子类。否则,可能会导致运行时异常。

总之,泛型的不可协变性导致无法直接将List赋值给List,但可以通过使用通配符和双重转型来解决这个问题。这种方法需要谨慎使用,确保转换是安全的。

0
0 Comments

Java泛型:无法将List转换为List

在第二种情况中,你看到的是数组协变。在我的观点中,这是一件不好的事情,它使得数组内的赋值是不安全的-尽管在编译时是正常的,但在执行时可能会失败。

在第一种情况中,想象一下,如果代码编译成功,并且接下来是这样的代码:

b1.add(new SomeOtherTree());

DataNode node = a1.get(0);

你会期望会发生什么呢?

你可以这样做:

List a1 = new ArrayList();

List b1 = a1;

因为你只能从b1中获取东西,并且它们保证与Tree兼容。你不能调用b1.add(...),因为编译器无法确定它是否安全。

可以参考Angelika Langer的Java泛型FAQ中的这一部分,获取更多信息。

ah..! 这个是有效的:List

谢谢解释。你能给出一个“在数组内部不安全-尽管在编译时是正常的,但在执行时可能会失败”的例子吗?--忽略它。我找到了例子。

SoNG: 是的,基本上做与我的“错误”例子相同的事情,只是在数组中设置一个值而已 🙂

我遇到了类似的情况,经过了很多搜索之后,我打算发布一个新问题,但是碰巧遇到了这个。我尝试了一个独立的Java类,其中有:

1. List x = new ArrayList();

2. List x = new ArrayList();

#1 编译正常,但是 #2 给出一个错误:不兼容的类型 found: java.util.ArrayList required: java.util.List

List x = new ArrayList();

这令人困惑,但幸好通过Java Generics FAQ解决了这个谜团! 🙂

List,真的很棘手。

:以什么方式?我不确定你的评论想要表达什么。

作为一个Java新手,我从来没有见过这样的用法。对我来说,这似乎有点复杂。

:啊,我明白了。我建议你阅读一下Java泛型教程-你会经常见到这个的。

如果我没有理解错,<?extends T>表示我们可以将任何T的子类型放入一个集合中。那么如何将两个子类T的列表合并成一个T的列表?

:对,就是这个意思。然后假设U extends T和V extends T,如果我们有一个List和一个List,我们可以将它们合并成一个List吗?

:是的,应该是可行的...如果你在实现时有困难,请提一个新问题并提供详细信息。

0