不兼容的类型,找到 List<capture<? 仅在 Java 8 中扩展模型>>

Orb*_*bit 1 java android java-8 android-studio rx-java2

我目前正在审查 Android 应用程序的更改,这些更改将应用​​程序升级为使用 Java 8。

在审查期间,我注意到以下代码被加下划线作为错误:

List<MappableTask> tasks = Observable.fromIterable(taskMapHoldingPresenter.getMappableTasks())
        .filter(isMappableTask)
        .toList()
        .blockingGet();
Run Code Online (Sandbox Code Playgroud)

现在显示以下内容:

Incompatible Types.
Required: List<MappableTask>
Found: List<capture<? extends MappableTask>>
Run Code Online (Sandbox Code Playgroud)

getMappableTasks()方法在接口中定义如下:

List<? extends MappableTask> getMappableTasks();
Run Code Online (Sandbox Code Playgroud)

请注意,这MappableTask是由各种模型类实现的接口。

怎么是List<MappableTask> list = taskMapHoldingPresenter.getMappableTasks();无效的?

此代码按预期构建。如上所述,在升级应用程序以使用 Java 8 之前未显示此错误。为什么会出现此问题?

hoa*_*oaz 5

您的接口声明允许getMappableTasks方法返回任何子MappableTask类的列表。假设MappableAsyncTask扩展MappableTask你的接口理论上可以返回List<MappableAsyncTask>.

class MappableAsyncTask extends MappableTask {
}

class AsyncPresenter implements TaskMapHoldingPresenter {
    @Override
    public List<? extends MappableTask> getMappableTasks() {
        List<MappableAsyncTask> result = new ArrayList<>();
        result.add(new MappableAsyncTask());
        return result;
    }
}
Run Code Online (Sandbox Code Playgroud)

List<MappableAsyncTask>不是 的子类List<MappableTask>,因此您不能将getMappableTasks结果分配给tasks变量。

List<MappableTask> tasks = asyncPresenter.getMappableTasks(); // wrong
Run Code Online (Sandbox Code Playgroud)

这种限制存在是有原因的。如果此分配是可能的,您可以轻松地将MappableTask实例添加到tasks列表中,从而打破实际的列表实现合同。请记住,getMappableTasks方法返回的实际列表只能包含MappableAsyncTask.

List<MappableTask> tasks = asyncPresenter.getMappableTasks(); // wrong
tasks.add(new MappableTask()); // wrong
Run Code Online (Sandbox Code Playgroud)

更多信息在这里