Liskov substitution principle 的一部分声明:
子类型的方法不应抛出新的异常,除非这些异常本身是超类型方法抛出的异常的子类型。
因此,当在客户端代码中用一种类型替换另一种类型时,任何异常处理代码都应该仍然有效。
如果您选择使用checked exceptions,Java 会为您强制执行此操作。 (不建议使用受检异常,但我将在此处使用来演示原理)。
这并不是说您应该捕获所有异常并进行转换。异常可能是意外的(即RuntimeExceptions 在检查异常环境中),您应该只翻译匹配的异常。
例子:
public class NotFoundException {
}
public interface Loader {
string load() throws NotFoundException;
}
用法:
public void clientCode(Loader loader) {
try{
string s = loader.load();
catch (NotFoundException ex){
// handle it
}
}
这是一个很好的实现,它可以捕获一个可以捕获和转换的异常,然后传播其余的异常。
public class FileLoader implements Loader {
public string load() throws NotFoundException {
try{
return readAll(file);
} catch (FileNotFoundException ex) {
throw new NotFoundException(); // OK to translate this specific exception
} catch (IOException ex) {
// catch other exception types we need to and that our interface does not
// support and wrap in runtime exception
throw new RuntimeException(ex);
}
}
}
这是翻译所有异常的糟糕代码,不需要满足 Liskov:
public class FileLoader implements Loader {
public string load() throws NotFoundException {
try{
return readAll(file);
} catch (Exception ex) {
throw new NotFoundException(); //assuming it's file not found is not good
}
}
}