使用未经检查和已检查异常的接口声明

Zac*_*ach 8 java exception-handling interface

我已经在下面搜索了我的问题的潜在答案,但没找到.

我理解已检查和未检查的异常之间的区别以及程序员可以/必须对它们执行的操作.但是,我不太明白编译器在接口方面如何解释未经检查的异常.

最近,我编写了一个类似于以下内容的接口和实现:

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!");
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这是我困惑的地方.以下实现也将编译:

public class Divide implements Operation {
    @Override
    public int operate(int x, int y) {
        return x / y;
    }
}
Run Code Online (Sandbox Code Playgroud)

为什么编译器不关心我已经将该方法声明为在接口中抛出异常?我理解,未经检查的异常是运行时异常,并且程序员不需要处理它们,但是不明白为什么当我在界面中明确声明我希望处理异常时它不会强迫我处理它.

有人可以解释为什么编译器会允许这种情况发生吗?

Rya*_*art 11

你很困惑"处理"继承规则的异常.当您实现或覆盖方法时,没有规则说新方法必须抛出与实现/重写方法完全相同的异常.唯一的规则是它不能抛出超出父方法允许异常范围的已检查异常.将界面视为与外界建立合同.它说,"任何调用此方法的人都必须准备好处理这些类型的异常".然后,实现者可以自由地抛出异常,知道它将被处理,但它们并不需要抛出异常.


gui*_*eak 7

除了之前的答案,还值得注意的是,此代码完全可以用于检查异常:

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...
    }
}
Run Code Online (Sandbox Code Playgroud)

但是当我们引用EnglishGermanTranslatorvia时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)
    }
}
Run Code Online (Sandbox Code Playgroud)