你是对的。
异常应位于使用的同一抽象级别。这就是为什么java 1.4 Throwable支持异常链接的原因。例如,对于使用数据库的服务或“存储”不可知的服务,没有必要抛出FileNotFoundException。
它可能是这样的:
public abstract class Data {
public abstract String read() throws DataUnavailableException;
}
class DataFile extends Data {
public String read() throws DataUnavailableException {
if( !this.file.exits() ) {
throw new DataUnavailableException( "Cannot read from ", file );
}
try {
....
} catch( IOException ioe ) {
throw new DataUnavailableException( ioe );
} finally {
...
}
}
class DataMemory extends Data {
public String read() {
// Everything is performed in memory. No exception expected.
}
}
class DataWebService extends Data {
public string read() throws DataUnavailableException {
// connect to some internet service
try {
...
} catch( UnknownHostException uhe ) {
throw new DataUnavailableException( uhe );
}
}
}
请记住,如果在编程时考虑到继承,则应针对特定方案进行仔细设计,并使用这些方案测试实现。显然,如果编写一个通用库更难,因为你不知道它将如何使用它。但大多数情况下,应用程序被限制在特定的域中。
您的新异常应该是“运行时”还是“已检查”?这取决于,一般规则是针对编程错误抛出运行时,并检查可恢复的条件。
如果可以通过正确编程(例如 NullPointerException 或 IndexOutOfBounds )来避免异常,请使用 Runtime
如果异常是由于程序员无法控制的一些外部资源(例如网络已关闭),并且有些事情可以做(在5分钟内显示重试消息或其他东西),那么应该使用检查的异常。
如果异常超出了程序员的控制范围,但无法执行任何操作,则可以使用 RuntimeException。例如,你应该写一个文件,但文件被删除了,你不能重新创建它或重试,然后程序应该失败(你无能为力),最有可能与运行时。
请参阅 Effective Java 中的以下两项:
- 对可恢复条件使用已检验异常,对编程错误使用运行时异常
- 引发适合于抽象的异常
我希望这有帮助。