我正在定义一个新的接口API ......诚然,这不是我经常做的事情。我想定义接口方法来抛出异常,为实现者提供一些灵活性。然后,他们可以选择抛出异常,抛出更具体的Exception子类,或者根本不抛出任何东西。我已经阅读了几次虽然很好地允许实现类这种灵活性,但使用“throws Exception”定义接口方法也是不好的。相反,建议将Exception(例如MyException)子类化并抛出子类。对这种做法的解释缺乏细节,那么有人可以详细说明这种最佳做法吗?感谢。
答案 0 :(得分:11)
我可以尝试为实施者提供一些灵活性,但 异常是API的一部分, 所以你应该考虑一下(检查)异常( s)有道理。
通过说throws Exception
,您没有帮助接口的客户了解预期会出现哪种类型的故障,从而使他们有机会对其作出适当的反应。您可以考虑接受Object
的方法参数,以允许实施者决定他们可以接受哪些参数。它对实现者有好处,但对于界面的客户来说却是一场噩梦。
答案 1 :(得分:3)
最好知道以后需要抛出的异常。 有所谓的Liskov替换原则,它建议不要在超类不会抛出的子类中抛出异常。
Liskov替代原则又名。按合同设计: http://en.wikipedia.org/wiki/Liskov_substitution_principle
如果您不确定需要抛出哪个Exception,请使用“throws Exception”(即使它是uncool)。只是在他们没有为您规划的情况下抛出异常时,不要通过实现类来允许意外行为。
最糟糕的情况是程序员由于缺少抛出声明而拼命抛出运行时异常。
答案 2 :(得分:2)
我更喜欢抛出RuntimeException
的Java标准子类。这样可以灵活地允许在不引用API的情况下传播或捕获异常。
有许多子类可供选择http://docs.oracle.com/javase/7/docs/api/java/lang/RuntimeException.html
我经常使用IllegalStateException
或IllegalArgumentException
答案 3 :(得分:2)
将已检查的异常视为可选的返回值。其方法返回Object
的API很少见,并且相同的原则应适用于已检查的异常。
答案 4 :(得分:1)
说明声明抛出基类Exception
的接口方法是不好的做法的原因是因为它实际上会使该基类的实例抛出一个合法的接口实现,这就是你显然想避免。
这就是您只在签名中使用专门/自定义异常类型的原因。
我不会说接口不应该事先声明抛出任何异常,正如有人在之前的回答中所说,因为接口实际上不是自由浮动的。
作为声明接口的人,您以某种方式调用或使用这些方法,并对代码方使用方法的方式进行断言。
这实际上是您创建的合约。 异常是合同的一部分。事实上,使用接口的人(而不是实现它的人)将在实施可能存在之前以他的工作方式完成。
答案 5 :(得分:1)
通常,抛出异常意味着两个选项之一:
专注于第一种类型抛出特定异常是一个好主意而且被调用可以做到:
try {
} catch (ServerIsBusyException ex) {
// wait 10 sec and continue / try another server
} catch (BadUserNameException ex2) {
// try another name
} ....
第二种类型通常是RuntimeException,这意味着意外情况
在此answer
中查看一个很好的解释