假设在Java中,我使用的是一个相当普遍的预先存在的接口
public interface Generator {
public String generate();
}
我有自己的班级
public class FromFileGenerator implements Generator {
...
public String generate() throws FileNotFoundException {
String output = //read from some file
return file;
}
}
Java编译器对我大吼大叫,因为generate()的实现包含未在原始签名中指定的异常(FileNotFoundException)。但是,显然异常不属于接口,但在实现类中也不能忽略。如果不是默默地失败,怎么能解决这个问题呢?
答案 0 :(得分:13)
您不能将已检查的异常添加到隐藏,覆盖或实现其他方法的方法的声明中。您需要在方法中捕获异常并对其执行其他操作(例如return null
,或者抛出未经检查的异常,可能包装已检查的异常)。
来自Java Language Specification, §8.4.8.3:
覆盖或隐藏另一个方法的方法(包括实现接口中定义的抽象方法的方法)可能不会被声明为抛出比重写或隐藏方法更多的已检查异常。
答案 1 :(得分:4)
不幸的是,没有办法很好地解决它:异常规范是接口的一部分,所以如果编程到你的Generator
接口的人不希望看到FileNotFoundException
,它不应该当他们使用FromFileGenerator
时,他们会来找他们。
解决此问题的常用方法是引入一个常见异常,并在其中包装FileNotFoundException
:
public class GeneratorException extends Exception {
public GeneratorException(Exception inner) {
super(inner);
}
}
public interface Generator {
public String generate() throws GeneratorException;
}
public class FromFileGenerator implements Generator {
...
public String generate() throws GeneratorException {
try {
String output = //read from some file
return file;
} catch (FileNotFoundException fnf) {
throw new GeneratorException(fnf);
}
}
}
答案 2 :(得分:4)
界面是合同。
所以你需要事先定义它。
因此,您可以尝试,在方法体内捕获或修改合同。
答案 3 :(得分:3)
您可以将实现异常包装在未经检查的异常中并抛出:
public class FromFileGenerator implements Generator {
...
public String generate() {
try {
String output = //read from some file
return file;
} catch (IOException ioe) {
throw new RuntimeException(ioe);
}
}
}
答案 4 :(得分:3)
常见的解决方法是将异常包装在未经检查的异常中。所以你的课可能看起来像:
public class FromFileGenerator implements Generator {
...
public String generate() throws FileNotFoundException {
try {
String output = //read from some file
return output
} catch (FileNotFoundException e) {
throw new IllegalStateException(e);
}
}
}
更好的方法是将接口更改为具有自己的已检查异常。然后,您可以将FileNotFoundException转换为该检查的异常,方法与转换为上面未经检查的IllegalStateException的方式相同。