我在下面搜索了我的问题的潜在答案,但没有找到答案。
我理解已检查和未检查的异常之间的区别以及程序员可以/必须对它们执行的操作。但是,我不太明白编译器在接口方面如何解释未经检查的异常。
最近,我编写了一个类似于以下内容的接口和实现:
public interface Operation {
int operate(int x, int y) throws ArithmeticException;
}
public class Divide implements Operation {
@Override
public int operate(int x, int y) throws ArithmeticException {
try {
return x / y;
} catch (ArithmeticException ex) {
System.out.println("Division error!");
}
}
}
这是我困惑的地方。以下实现也将编译:
public class Divide implements Operation {
@Override
public int operate(int x, int y) {
return x / y;
}
}
为什么编译器不关心我已经将该方法声明为在接口中抛出异常?我理解未经检查的异常是运行时异常,并且程序员不需要处理它们,但是不明白为什么当我在界面中明确声明我希望处理异常时它不会强迫我处理它。
有人可以解释为什么编译器会允许这种情况发生吗?
答案 0 :(得分:10)
您使用继承规则混淆“处理”异常。实现或覆盖方法时,没有规则说新方法必须抛出与实现/重写方法完全相同的异常。唯一的规则是它不能抛出超出父方法允许异常范围的已检查异常。将界面视为与外界建立合同。它说,“任何调用此方法的人都必须准备好处理这些类型的异常”。然后,实现者可以自由地抛出异常,知道它将被处理,但它们决不会必需抛出异常。
答案 1 :(得分:6)
除了之前的答案之外,值得注意的是,此代码完全可以用于检查异常:
interface Translator {
String translate(String s) throws IOException; /* <-- Checked exception */
}
class EnglishGermanTranslator implements Translator {
@Override
public String translate(String s) { // <-- no exception, but its ok
return ""; // logic is irrelevant...
}
}
public class Test {
public static void main(String[] args) {
EnglishGermanTranslator t = new EnglishGermanTranslator();
t.translate("Text to translate"); // No problems...
}
}
但是当我们通过EnglishGermanTranslator
引用Translator
时,我们必须抓住一个适当的例外:
public class Test {
public static void main(String[] args) {
Translator t = new EnglishGermanTranslator();
t.translate("Text to translate"); // <-- compilation error... try-catch required (or throws in main)
}
}
答案 2 :(得分:4)
在throws
子句中声明运行时异常仅用于信息(和javadoc) - 以便您的类/接口的用户知道在给定情况下会发生什么。
由于它们是运行时,编译器不会对它们强制执行任何操作 - 既不捕获也不声明。