我有一个从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()不是问题。只是复制相同错误消息的实际代码的简化。
这是代码的图像。
最佳答案
看来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
来取消该默认方法的空默认值。仍然是期望的。