可调用:为什么我们可以“改变”实现中的异常?

时间:2013-06-06 09:16:00

标签: java exception-handling

此代码编译时没有错误:

private FutureTask<MessageSource> loadingTask(final Locale locale)
{
    return new FutureTask<MessageSource>(new Callable<MessageSource>()
    {
        @Override
        public MessageSource call()
            throws IOException
        {
            return loader.load(locale);
        }
    });
}

但是Callable接口定义了这个:

public V call()
    throws Exception;

为什么我可以声明我的覆盖会抛出IOException

注意:我已经看过并利用了Guava的CacheLoader

2 个答案:

答案 0 :(得分:4)

简短的回答:你可以这样做,因为IOException是一个Exception

public V call() throws Exception

表示“此方法可以抛出Exception而没有其他已检查的异常!”。

如果你现在覆盖这个方法:

public MessageSource call() throws IOException

你实际上是在说“我们会被允许抛出任何Exception但我们自愿将自己限制为一个子集:IOException及其子女”。

你甚至可以这样做:

public Something call()

根本没有throws:“我们将被允许抛出任何Exception,但我保证我们不会抛出任何已检查的异常!”

答案 1 :(得分:2)

当覆盖抛出一些异常的方法时,overriden方法必须抛出与覆盖方法或其某些超类相同的异常。

JLS #8.4.8.3

中对此进行了描述
  

假设B是类或接口,AB的超类或超接口,n中的方法声明B会覆盖或隐藏m中的方法声明A。然后:

     
      
  • 如果nthrows子句提及任何已检查的异常类型,则m必须具有throws子句,否则会发生编译时错误。
  •   
  • 对于n的throws子句中列出的每个已检查异常类型,throws m子句的删除中必须出现相同的异常类或其中一个超类型;否则,发生编译时错误。
  •   

(其中n会覆盖m