抛出语句不考虑继承的异常

时间:2015-04-07 19:23:41

标签: java exception-handling throws checked-exceptions

我有两个例外:

class MyException1 extends Exception {
 --
}

class MyException2 extends MyException1 {
--
}


function invokeValidation() throws MyException2 {

    obj1.method() // it throws MyException1
    obj2.method() // it throws MyException2
}

上面的代码显示unhandled exception type MyException1, 即使MyException2延伸MyException1。为什么它会在throws语句中期望MyException1

3 个答案:

答案 0 :(得分:3)

如果obj1.method()抛出MyException1,则可能会抛出MyException1的非MyException2子类(或MyException2的子类)。因此,仅仅声明invokeValidation()抛出MyException2

是不够的

另一方面,如果您声明invokeValidation() throws MyException1,那就足够了,因为任何MyException2例外也是MyException1

答案 1 :(得分:2)

我认为如果您使用更有意义的异常名称,您可能会更清楚,因为您的异常命名并不能反映异常的真实目的。

例如,假设您的Exception1现在是IOException。它表明存在一些输入输出问题。您的扩展异常现在称为Exception2,而不是FileNotFoundException。它表示特定的输入输出错误 - 找不到文件。

因此,正如您所见,FileNotFoundException 类型的IOException。这就是extends定义的关系。

现在想象一下你的方法是否被声明:

public void invokeValidation() throws FileNotFoundException {

    obj1.method(); // it throws IOException
    obj2.method(); // it throws FileNotfoundException
}

所以,你说"我的方法抛出FileNotFoundException"。编译器知道如果它遇到这个特殊的Exception,它应该把它扔给调用者。但是obj1可能会抛出IOException。它可能是一个异常,表示磁盘上没有空间。或者说有一个坏块。或者文件突然关闭。这可能是很多事情。 IOException FileNotFoundException。因此,编译器与它没有任何关系,它告诉你这是一个未处理的异常。

但是如果声明了你的方法:

public void invokeValidation() throws IOException {

    obj1.method(); // it throws IOException
    obj2.method(); // it throws FileNotfoundException
}

编译器不会抱怨。为什么?因为对于obj1,它会抛出一个IOException,这很好,它就在标题中,它可以被抛出一级。对于obj2,它知道FileNotFoundException (类型)IOException,因此允许它抛出它。它与IOException是多态的,调用者将知道如何处理它。

所以继承的层次结构很重要。如果你有两个方法抛出两个异常,一个是另一个的超类,你应该声明你的方法抛出超类。因为任何子类都有一个" is_A"与超类的关系。它是超类的特定类型。但事实恰恰相反。

答案 2 :(得分:1)

你总是抛出异常及其子类,而不是相反(如果是这种情况,你总是抛出Throwable)。

想象一下MyException2有一个变量:

String name = "whatever";

现在,如果你抛出一个MyException1的实例,但是其他地方捕获了MyException2,那么它就会出错,因为你不能从更特殊的类中向其超类类型转换。 MyException1中没有字段名称。

反过来总是有效,因为MyException2继承了MyException1的所有字段。