当您需要抛出未在您正在实现的接口中定义的异常时,要遵循的最佳做法是什么?
以下是一个例子:
public interface Reader
{
public abstract void read() throws IOException;
}
public class CarrotReader implements Reader
{
public void read() throws IOException {}
}
public class CupcakeReader implements Reader
{
public void read() throws IOException, CupcakeException {}
}
在这种情况下,您在阅读纸杯蛋糕时会发生特定异常,因此您希望抛出与此相关的异常。但是, Reader 没有在其界面中定义此类异常,那么您如何做?此外,将 CupcakeException 添加到 Reader 接口中的 throws 子句没有意义,因为这种类型的异常特定于< EM> CupcakeReader 。解决这个问题的一种方法是让 Reader 定义 read ,这样它会抛出一些父类型,比如 Exception ,但是你会失去上下文例外。在这种情况下你应该怎么做?谢谢!
另一个有趣的情况涉及一个你无法控制的界面。在这种情况下,表明问题发生的最佳方法是什么?
为了便于说明,这是另一个例子:
public interface Reader
{
public abstract void read();
}
public class CupcakeReader implements Reader
{
public void read() throws CupcakeException {}
}
在这种情况下,您无法更改 Reader ,但您想表明 CupcakeReader 的读取方法中出现了问题。
答案 0 :(得分:13)
您可能需要创建预期类型的例外。
... catch(CupcakeException e) {
throw new IOException("The sky is falling", e);
}
答案 1 :(得分:9)
使用名为ReaderException的东西,它将作为异常层次结构的根接口。 ReaderException还将提供指向由于较低级别异常而引发的其他异常的链接。
答案 2 :(得分:2)
异常是界面的一部分。如果可以重新定义接口,请为接口中的所有异常定义通用父级。
您还可以将CupcakeException设为IOException的子级。
答案 3 :(得分:1)
请勿使用已检查的例外情况。
您展示的示例是检查异常不良的原因之一。
主要原因是你的蛋糕读者的使用者必须处理你的例外,无论他是否对此感兴趣。
所以而不是:
Value value = reader.read();
你强迫他这样做:
Value value = null;
try {
value = reader.read();
} catch (Exception e) {
// now what??
}
value.doSomething(); // potential NPE here
考虑哪一个更好,更易读,更不容易出错,只是停止使用已检查的异常。
修改强>
我对负面评价感到惊讶。有人仍然认为检查异常是伟大的吗?如果是这样,这里有一些参考,为什么你不应该使用检查的例外:
答案 4 :(得分:0)
也许你可以创建一个抽象的ReaderSpecificException类,把它放在接口中,然后 从这个抽象类中继承CupcakeException。
答案 5 :(得分:0)
如果创建一个更高的抽象异常作为CupCakeException的基类,则不要将Reader接口绑定到特定的实现,就像将CupCakeException添加到Reader接口时一样。 如果你不让一个Exception从另一个继承,那么在异常类中有一个constructor,它将一个throwable作为第二个参数,比如ThorbjørnRavnAndersen已经在他的短代码示例中展示了。这使您能够生成更抽象的异常,并且代码的每个部分都需要知道更多,然后只是“有错误”可以查找更高异常的原因。