什么放在接口方法的throws子句中?

vit*_*aut 5 java oop exception

假设我有接口I和两个类AB实现它.f此接口的方法的实现A抛出一组异常并且实现B抛出另一组.这些例外的唯一共同祖先是java.lang.Exception.在这种情况下申报f投掷是否合理java.lang.Exception?还有其他选择吗?

我之所以要问的原因是,一方面java.lang.Exception对我来说似乎太笼统,另一方面列出所有异常似乎不切实际,考虑到可能的其他实现.

例:

interface I {
    void f() throws Exception;
}

class A implements I {
    public void f() throws IOException {}
}

class B implements I {
    public void f() throws InterruptedException {}
}
Run Code Online (Sandbox Code Playgroud)

Adr*_*onk 16

使用接口的原因是抽象出实现细节.

通过抛出这些异常,您将暴露可能应该被抽象出来的实现细节.

也许最好定义一个新的例外.然后f()的每个实现都将捕获它所知道的异常并抛出新的异常,所以你有:

interface I {
    void f() throws MyException;
}

class A implements I {
    public void f() throws MyException {
         try {
             ...
         } catch (IOException e) {
             throw new MyException(e);
         }
    }
}

class B implements I {
    public void f() throws MyException {
         try {
             ...
         } catch (InterruptedException e) {
             throw new MyException(e);
         }
    }
}
Run Code Online (Sandbox Code Playgroud)

通过包装实现异常,您仍然将它暴露给调用者,并且当您调用远程方法时可能会咬你.在这些情况下,您需要做更多工作以通用方式返回有用信息.

编辑
关于正确的方法似乎存在一些争议.

当我们调用f()时,我们需要以下代码:

I instanceOfI = getI();
try {
    instanceOfI.f();
}
catch ( /* What should go here ? */ )
Run Code Online (Sandbox Code Playgroud)

它归结为什么是一个很好的Exception类放在catch块中.
使用OP的原始代码,我们可以捕获Exception,然后可能会尝试查看我们拥有哪个子类,或者根据需求.或者我们可以单独捕获每个子类,但是当新实现抛出不同的异常时我们必须添加catch块.

如果我们使用运行时异常,那么除了我们可以将异常处理推迟到调用方法而不用任何想法的异常可能性之外,它会变得很相似.

如果我们使用了我使用新的包装异常的建议,那么这意味着我们必须捕获MyException然后尝试查看可用的其他信息.这基本上就像使用Exception一样,但需要额外的工作bespoke才能获得可以根据目的定制的异常的有限好处.