使用接口隐藏了实现抛出的异常

时间:2016-02-23 22:27:39

标签: java exception interface implementation

给出以下代码:

interface Provider
{
    String getStuff();
}

class CustomProvider implements Provider
{
    public String getStuff() throws RuntimeException
    {
        // possibly throwing an exception

        return "some stuff";
    }
}

class Main
{
    public static void main(String[] args)
    {
        Main main = new Main();
        main.test(new CustomProvider());
    }

    public void test(Provider provider)
    {
        provider.getStuff(); // we don't know that this can throw an exception!
    }
}

在这种特殊情况下,我们知道但在另一种情况下可能不会。

我们如何防止接口实现抛出未经检查的异常但客户端方法不知道接口的具体实现?

有时,如果有未经检查的异常,您实际上永远不会知道调用方法是否可以抛出异常。

解决方案可能是在界面中更改方法的签名:

interface Provider
{
    String getStuff() throws Exception;
}

这将确保该方法的客户端将被告知可以在所有实现中抛出异常。这个问题是,接口的任何实现都不会实际抛出异常。同时发出"抛出异常"在接口的每个方法看起来有点奇怪。

1 个答案:

答案 0 :(得分:0)

  

有时,如果有未经检查的异常,您实际上永远不会知道调用方法是否可以抛出异常。

编译器不检查未经检查的异常。您可以记录接口的约束,但编译器不会自动验证它们。

您建议声明该方法抛出异常。更有约束的方法是声明该方法抛出一些已检查的异常。

例如,您可以明确声明您的方法可能抛出I / O异常,如下所示。然后,调用者只需处理或抛出IOException,而不是更多可能的异常。

interface Provider
{
    String getStuff() throws IOException;
}

另一种选择是声明一种特殊的异常类型。这允许接口通过调用者宣传异常合同,而不限制实现可以遇到的异常类型。

interface Provider
{
    String getStuff() throws ProviderException;
}

class MyProvider implements Provider {
    public String getStuff() throws ProviderException {
       try {
          ...
       } catch ( IOException e ) {
          throw new ProviderException( e );
       }
    }
}

public class ProviderException extends Exception {
    public ProviderException( Exception cause ) {
        super( cause );
    }
    ...
}