Java 将元素添加到wildchar列表会导致编译错误

Java 将元素添加到wildchar列表会导致编译错误,java,generics,Java,Generics,我有一个列表包含将来的任务,将来的类型未知,所以我创建了一个通配符类型为?的列表,但是当我向列表中添加元素时,会发生编译错误 代码如下: private List<Pair<String, Future<?>>> futureTasks = Collections.synchronizedList( new ArrayList<Pair<String, Future<?>>>(8)); // taskId

我有一个列表包含将来的任务,将来的类型未知,所以我创建了一个通配符类型为
的列表,但是当我向列表中添加元素时,会发生编译错误

代码如下:

private List<Pair<String, Future<?>>> futureTasks = Collections.synchronizedList(
        new ArrayList<Pair<String, Future<?>>>(8));

// taskId is a string
futureTasks.add(Pair.makePair(taskId, getExecutors().submit(
    new Callable<String>() {
        public String call() {
            try {
                return exportAccountSrcTask(tmpFile); // return a string
            } catch (Exception e) {
                logger.error("failed to export account src", e);
            }
            return null;
    }}))
);
私有列表>>
不适用于参数
(成对)


出现错误是因为
不是
对>
。然后您就可以向它添加一对

编辑:

为了更好地解释这一点,可以考虑尝试将对象分配给变量,而不是将其添加到列表中。如果我们有一个
列表
,我们只能添加一个
T
对象。因此,情况也是如此:

Pair<String, Future<String>> pairOfStringAndFutureOfString;
Pair<String, Future<?>> pairOfStringAndFutureOfSomething;

// incompatible types
pairOfStringAndFutureOfSomething = pairOfStringAndFutureOfString;
这个变量名很有意思,但我希望它能准确地描述这里发生的事情。之前,第二个类型参数正好是
Future
。现在,我们说它是“某种未知类型,它是或扩展了
未来
。例如,它可能是
未来
,它可能是
未来
,甚至可能是
我的专业未来

我们自愿放弃有关此变量类型的一些信息,以便放宽可分配给它的内容。现在,这是合法的:

pairOfStringAndSomethingThatIsAFutureOfSomething = pairOfStringAndFutureOfString;
编译器通过防止“消耗”此未知类型来防止早期的“堆污染”情况:


要了解有关这些检索的更多信息,请参阅此帖子:

由于
不是
,因此您将得到一个错误。然后您将能够向其添加

编辑:

为了更好地解释这一点,请考虑尝试将对象分配给变量,而不是将其添加到列表中。如果我们有一个
列表
,则只有当对象是
T
时,我们才能添加该对象。因此,这实际上是相同的情况:

Pair<String, Future<String>> pairOfStringAndFutureOfString;
Pair<String, Future<?>> pairOfStringAndFutureOfSomething;

// incompatible types
pairOfStringAndFutureOfSomething = pairOfStringAndFutureOfString;
这个变量名很有意思,但我希望它能准确地描述这里发生的事情。之前,第二个类型参数正好是
Future
。现在,我们说它是“某个未知类型,它是或扩展了
Future
。例如,它可以是
Future
,也可以是
Future
,甚至可以是
MySpecialFuture

我们自愿放弃一些关于这个变量类型的信息,以便放松可以分配给它的内容。现在,这是合法的:

pairOfStringAndSomethingThatIsAFutureOfSomething = pairOfStringAndFutureOfString;
编译器通过防止“消耗”此未知类型来防止早期的“堆污染”情况:


要了解有关这些检索的更多信息,请参阅以下帖子:

为什么不能将其声明为
列表
?未来可能不确定,然后将其声明为
列表
。至于为什么不能使用通配符“
”和@MattBall添加()
,这实际上是一个不同的问题,因为它涉及一个嵌套的通配符。为什么不能将其声明为
List
?未来可能不确定,然后将其声明为
List
。至于为什么不能使用通配符“
.add()”
:和@MattBall,这实际上是一个不同的问题,因为它涉及一个嵌套的通配符。@jamee查看我的编辑,如果您还有其他问题,请告诉我。似乎我可以将Pair和Pair添加到List@jamee是的,没错,因为它们都是
Pair@jamee重要的是要认识到顶级通配符和嵌套通配符之间有很大的区别。有关更多信息,请参阅本文:@jamee查看我的编辑,如果您还有其他问题,请告诉我。似乎我可以将Pair和Pair添加到List@jamee是的,这是正确的,因为它们都是
Pair@jamee重要的是要认识到顶级通配符和嵌套通配符之间有很大的区别。有关更多信息,请参阅本文:
//compiler error - nothing can be legally passed into setRight
pairOfStringAndSomethingThatIsAFutureOfSomething.setRight(futureOfSomething);