我有一个从java.util.concurrent.AbstractExecutorService派生的类。我的课程覆盖了shutdownNow()。一切都可以编译并正常运行。

我在班上加了org.eclipse.jdt.annotation.@NonNullByDefault。我设法修复了所有错误和警告,除了shutdownNow()上的1个错误。错误消息显示...


返回类型与从ExecutorService.shutdownNow()返回的“列表”不兼容
(不匹配的空约束)


快速修复没有任何帮助。

这是令人反感的代码。

@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()不是问题。只是复制相同错误消息的实际代码的简化。

这是代码的图像。

java - @NonNullByDefault返回类型与从ExecutorService.shutdownNow()返回的&#39;List &lt;Runnable&gt;&#39;不兼容(不匹配null约束)-LMLPHP

最佳答案

看来ExecutorService不在任何@NonNullByDefault的范围内,对吗?

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

但是,替代会受到@NonNullByDefault使其有效签名@NonNull List<@NonNull Runnable> shutdownNow()的影响。

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

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

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

如果由于某种原因,注释超级接口不可行,即希望继续使用“旧式”类型List<Runnable>,则可以通过说出@NonNullByDefault({})并手动添加@NonNull来取消该默认方法的空默认值。仍然是期望的。

07-24 09:19