@NonNullByDefault return 类型与从 ExecutorService.shutdownNow() 编辑的 'List<Runnable>' return 不兼容(空约束不匹配)

@NonNullByDefault The return type is incompatible with 'List<Runnable>' returned from ExecutorService.shutdownNow() (mismatching null constraints)

我有一个 class 派生自 java.util.concurrent.AbstractExecutorService。我的 class 覆盖了 shutdownNow()。一切都编译并运行良好。

我将 org.eclipse.jdt.annotation.@NonNullByDefault 添加到 class。我设法修复了所有错误和警告,除了 shutdownNow() 上的 1 个错误。错误消息说...

The return type is incompatible with 'List' returned from ExecutorService.shutdownNow() (mismatching null constraints)

快速修复没有任何帮助。

这是有问题的代码。

@NonNullByDefault    // Adding this causes an error
public abstract class ShutdownThreadPool extends AbstractExecutorService implements ExecutorService
{
   @Override
   public List<Runnable> shutdownNow()   // The error is on this line
   {
      return(Collections.emptyList());
   }
}

注意:Collections.emptyList() 不是问题所在。它只是对重现相同错误消息的实际代码的简化。

这是代码的图片。

好像ExecutorService不在任何@NonNullByDefault的范围内吧?

此外,ExecutorService 声明 List<Runnable> shutdownNow()

然而,覆盖受到 @NonNullByDefault 的影响,使其有效签名 @NonNull List<@NonNull Runnable> shutdownNow()

不幸的是,快速修复只针对第一个 @NonNull,而类型参数 Runnable 上的注释实际上导致了不兼容:

我们不知道 ExecutorService.shutdownNow() 的预期语义:客户应该期望返回列表中有可为空或非空的元素吗?假设 List<@NonNull Runnable> 会破坏喜欢将 null 插入结果列表的 shutdownNow() 的潜在调用者(忽略这暗示的奇怪设计)。

为了使这个覆盖类型安全,应该首先在超级接口上引入空注释(在这种情况下使用外部注释),然后让实现跟随套件。

如果出于任何原因注释超级接口不可行,即需要继续使用 "legacy" 类型 List<Runnable>,则可以通过说 [= 取消此方法的空默认值23=],并在仍然需要的地方手动添加 @NonNull