类型不兼容:无法将SomeX转换为CAP#1

7
我不明白这里出了什么问题。
import java.util.*;

class Main {
    private static class SomeX {}

    void doSomethingWithX(SomeX someX) {
        Collection<? extends SomeX> colectionOfX = new ArrayList<>();
        colectionOfX.add(someX);
    }
}

javac 的意思是:

  Main.java:8: error: method add in interface Collection<E> cannot be applied to given types;
          colectionOfX.add(someX);
                      ^
    required: CAP#1
    found: SomeX
    reason: argument mismatch; SomeX cannot be converted to CAP#1
    where E is a type-variable:
      E extends Object declared in interface Collection
    where CAP#1 is a fresh type-variable:
      CAP#1 extends SomeX from capture of ? extends SomeX
据我理解,extends将CAP#1的下限限制为SomeX,并且SomeX本身也应满足这个限制。但是这段代码有什么问题呢?(使用javac 1.8.0_102编译)
2个回答

1
如果您想允许 colectionOfX 包含任何 SomeX 的实例,它应该声明为:
Collection<SomeX> colectionOfX = new ArrayList<>();

当你将其声明为

,保留HTML代码。
Collection<? extends SomeX> colectionOfX = ...;

它的意思是你可以给它分配任何持有某些类型的元素的Collection,这些类型要么是SomeX,要么是SomeX的子类。
例如,您可以将List<SomeBX>分配给它,其中SomeBX扩展了SomeX。在这种情况下,只能向集合添加SomeBX的实例。 因此,如果您尝试向集合添加一个不是SomeBX(例如,SomeAX的实例,它也是SomeX的子类)的SomeX实例,则无效。

1
那么...所有这些都没有回答“为什么我不能将SomeX的实例添加到Collection<? extends SomeX>中”的问题。在那个特定的操作中有什么问题? - Xtra Coder
正如我所解释的那样,“Collection<? extends SomeX> colectionOfX”不接受“SomeX”的所有实例。即使您将“new ArrayList<SomeX>()”赋值给它,您应该能够添加“SomeX”的任何实例,但编译器也无法知道这一点,因为它仅依赖于编译时类型,即“Collection<? extends SomeX>”。 - Eran

1

所以,问题实际上已经在 "如何向List<? extends Number>数据结构添加元素?" 中得到了回答,但是谷歌搜索并没有找到这个匹配项。

简短的答案,就我所知,如下:

class Main {
    private static class SomeX {}

    private static class SomeY extends SomeX {}

    void doSomethingWithX(SomeX someX) {
        Collection<? extends SomeX> colectionOfX = new ArrayList<SomeY>();
        colectionOfX.add(someX);
    }
}

因为<? extends SomeX>更像是集合类型的下限限制而不是元素类型,所以可以将具有更高上限值的集合实例分配给它,并且考虑到这一点,从编译器的角度来看,在这样的集合中放置SomeX并不是类型安全的。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接