什么放在接口方法的throws子句中? [英] What to put in the throws clause of an interface method?

查看:191
本文介绍了什么放在接口方法的throws子句中?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有接口和两个类 A B 实现它。
A 中此接口的方法 f 的实现会抛出一组异常并在 B 抛出另一组。这些异常的唯一共同祖先是 java.lang.Exception 。在这种情况下声明 f 抛出 java.lang.Exception 是否合理?还有其他选择吗?

Suppose I have interface I and two classes A and B that implement it. The implementation of method f of this interface in A throws one set of exceptions and the implementation in B throws another set. The only common ancestor of these exceptions is java.lang.Exception. Is it reasonable to declare f throwing java.lang.Exception in this case? Any other alternatives?

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

The reason why I am asking is that on the one hand java.lang.Exception seems too general to me and one the other hand listing all exceptions seems impractical considering possible other implementations.

示例:

interface I {
    void f() throws Exception;
}

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

class B implements I {
    public void f() throws InterruptedException {}
}


推荐答案

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

The reason for using an interface is to abstract away the implementation details.

通过抛出这些异常,你暴露了可能应该是的实现细节抽象而已。

By throwing these exceptions, you're exposing implementation details that probably should be abstracted away.

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

Perhaps it would be best to define a new exception. Then each implementation of f() would catch the exceptions it knows about and throw the new exception instead so you'd have:

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);
         }
    }
}

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

By wrapping the implementation exception, you're still exposing it to the caller and that can bite you when you're calling remote methods. In those cases you need to do more work to return useful information in a generic way.

编辑

似乎关于正确的方法有点争议。

Edit
There seems to be a bit of a dispute going on about the correct approach.

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

When we call f(), we'll need code like:

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

它归结为什么是一个好的Exception类放在catch块中。

使用OP的原始代码我们可以捕获异常然后尝试根据要求查看我们拥有或不具备的子类。或者我们可以单独捕获每个子类,但是当新实现抛出不同的异常时我们必须添加catch块。

It comes down to what is a good Exception class to put in the catch block.
With OP's original code we could catch Exception and then maybe try to see which subclass we have, or not depending on requirements. Or we could individually catch each subclass but then we'd have to add catch blocks when new implementations throw different exceptions.

如果我们使用运行时异常,那么它会得到很多同样的事情,除了我们可以选择将异常处理推迟到调用方法,甚至没有任何想法的可能性。

If we used Runtime exceptions it would come to much the same thing except that we could alternatively defer the exception handling to a caller method without even giving the possibility of exceptions any thought.

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

If we used my suggestion of using a new, wrapped exception then this means we have to catch MyException and then try to see what additional information is available. This essentially becomes very like just using an Exception, but requires extra work for the limited benefit of having a bespoke exception that can be tailored to the purpose.

这篇关于什么放在接口方法的throws子句中?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆