假设我有以下我可能修改的Java接口:
public interface MyInterface {
public void doSomething();
}
现在实现它的类是这样的:
class MyImplementation implements MyInterface {
public void doSomething() {
try {
// read file
} catch (IOException e) {
// what to do?
}
}
}
我无法从不读文件中恢复过来。
RuntimeException
的子类可以明显地帮助我,但我不确定这是否是正确的做法:问题是该异常不会记录在类和类的用户中可能会得到这个例外,对解决这个问题一无所知。
我该怎么办?
我们都同意:界面有问题。
解决方案我选择了
我最后决定写一个MyVeryOwnInterface
扩展MyInterface
并添加MyRuntimeException
public interface MyVeryOwnInterface extends MyInterface {
public void doSomething() throws MyRuntimeException;
}
class MyImplementation implements MyVeryOwnInterface {
public void doSomething() throws MyRuntimeException {
try {
// read file
} catch (IOException e) {
throw new MyRuntimeException("Could not read the file", e);
}
}
}
答案 0 :(得分:8)
您遇到了leaky abstractions的问题。没有非常好的解决方案,使用RuntimeException
几乎是你唯一可以做的事情。
可以说,这也是为什么检查异常是失败概念的一个例子。
答案 1 :(得分:3)
我会抛出new IOError(e);
并在界面的维护者处提出问题。
答案 2 :(得分:2)
如果你无法恢复而不需要抛出它,那么将它包装成RuntimeException或Error并抛出它。
public class Unchecked extends Error {
private final Exception source;
public Unchecked( Exception source) {
this.source = source;
}
public String toString() {
return "Unchecked Exception, Caused by: " + source;
}
public Exception getSource() {
return source;
}
public static Unchecked wrap( Exception cause ) {
return new Unchecked(cause);
}
}
答案 3 :(得分:1)
显然,接口设计人员没有考虑doSomething()可能失败的可能性。理想情况下,他应该允许抛出IOException(如果他怀疑IO会被调用)或者可以用来封装IOException的SomethingException(checked)。
如果您可以使用界面设计人员,请与他们交谈并询问他们在发生故障时会发生什么。也许他们可以改变界面:或者根据接口的合同默认失败是可以接受的。
所有这些都失败了你可以选择默默地失败(可能是录音但没有响应问题)或抛出可能终止进程的RuntimeException。
答案 4 :(得分:0)
除了在界面中声明throws IOException
之外,我认为没有任何事情要做。
这只是Java接口和已检查异常的本质。
您可以在类(doSomethingDangerous
)中使用另一种方法抛出IOException
。从doSomething
- 实现中,您只需调用doSomethingDangerous(包含在try / catch中),然后您希望在doingSomething
时直接调用doSomethingDangerous
。
答案 5 :(得分:0)
我建议
throw new RuntimeException("while reading file " + fileName + "...", e);
这不是问题,界面根本不会出现任何问题吗?
(您可能想要创建自己的OurCompanyDomainException扩展RuntimeException,以便在界面另一端的代码中轻松区分。)