我可以实现抛出最初在接口中抛出的异常子类型的方法吗?



在我的程序中有两个例外:

class AnException extends Exception {};
class SpecialException extends AnException{};

我有一个接口,定义方法抛出AnException:

interface TheInterface {
    public void method() throws AnException;
}

AnException衍生出更多的例外,TheInterface有更多的实现。这就是为什么我希望它们抛出它们原来的异常,并将它们强制转换为AnException:

public class Implementation1 implements TheInterface {
    //Error: Overriden method does not throw AnException
    public void method() throws SpecialException {
    }
}
在这一刻,AnExpception的衍生物似乎是浪费时间,因为它们从未被使用,并立即被强制转换为它们的祖先。然而,它们不是由method()直接抛出的,它们有存在的理由。看看我尝试过的这个解决方案:
@Override
public void method() throws AnExpception {
    try {
        return new OtherClassThatThrowsExceptions();
    }
    catch(SpecialException e) {
        //Netbeans says that I can't cast SpecialException to AnException
        throw (AnExpception)e;   
    }
}

其实我不知道你的问题是什么。如果您正在询问是否可以用更指定的异常重写方法,那么答案是

看一下。假设我们有异常和与基方法的接口

class AnException extends Exception {};
class SpecialException extends AnException {};
interface TheInterface {
    public void method() throws AnException;
}

现在让我们看看编译器是否允许用更指定的异常重写方法

class Implementation1 implements TheInterface {
    @Override  
    public void method() throws SpecialException {
        throw new SpecialException();
    }
}
如您所见,它编译得很好,因为这种方法没有可能出现的问题。

假设你使用TheInterface类型的引用并且它保存Implementation1的实例

TheInterface interface1 = new Implementation1();

如果你想从这样的参考编译器中使用method,将需要你处理AnException,因为它不能确定interface1在执行此方法时所持有的对象的确切类型。所以你需要写一些像

这样的东西
try {
    interface1.method();
} catch (AnException e) {
    System.err.println("exception "+ e.getClass().getSimpleName()+ " handled");
}

,因为catch (AnException e)也会捕获实际抛出的SpecialException,因为它是AnException的子类型,所以保证会处理异常。

如果你要使用Implementation1实例的精确引用类型

Implementation1 implementation1 = new Implementation1();

编译器将要求您处理SpecialException,因为该异常在方法签名中指定。所以如果你想从这个引用中调用method,你需要写

try {
    implementation1.method();
} catch (SpecialException e) {
    System.err.println("exception "+ e.getClass().getSimpleName()+ " handled");
}

和你的异常保证被处理

最新更新