简体   繁体   English

可以使用已检查的异常抛出未检查的异常吗?

[英]Can a checked exception be used to throw an unchecked exception?

I am running the following code:我正在运行以下代码:

import java.io.FileNotFoundException;
import java.io.IOException;

class Basic1 {
    int c;

    void calculation(int a, int b) throws Exception {
        c = a / b;
    }
}

class Basic extends Basic1 {
    void calculation(int a, int b) throws IOException {
        c = a / b;
        RuntimeException ae = new ArithmeticException();
        throw ae;
    }

    public static void main(String[] args) {
        int a = 10;
        int b = 0;
        int c;
        Basic ba = new Basic();
        try {
            ba.calculation(a, b);
        } catch (IOException e) {
            System.out.println("Zero can't be there in the denominator. : IoException");
        } catch (ArithmeticException e) {
            System.out.println("Zero can't be there in the denominator. : Arthimetic Exception");
        } catch (Exception e) {
            System.out.println("Zero can't be there in the denominator. : Exception");
        }
    }
}

The program is compiling successfully and outputting "Zero can't be there in the denominator. : Arthimetic Exception" (output is as expected).程序编译成功并输出“分母中不能有零。:算术异常”(输出如预期)。

My question is how is the program able to compile successfully?我的问题是程序如何能够成功编译? Why am I not getting an error when I throw an IOException while inside calculation() I am creating a RuntimeException object?为什么我在创建RuntimeException对象时在calculation()抛出IOException时没有收到错误?

My second question is given that the program enters the catch (ArithmeticException e) clause, is the compiler deciding at run time which catch will execute?我的第二个问题是程序进入catch (ArithmeticException e)子句,编译器是否在运行时决定执行哪个catch Do I understand correctly?我理解正确吗?

For your first question, methods using the throws E (where E is some arbitrary checked exception) construct don't have to throw anything.对于您的第一个问题,使用throws E (其中E是一些任意检查的异常)构造的方法不必抛出任何内容。 All it means is that anyone calling your method has to be able to handle E , which allows your method to throw E without handling it.这意味着任何调用您的方法的人都必须能够处理E ,这允许您的方法在不处理它的情况下抛出E This would otherwise be a compilation error.否则这将是一个编译错误。 Usually, the documentation of your method specifies when E is thrown.通常,您的方法的文档会指定何时抛出E In the words of the JLS:用 JLS 的话来说:

Essentially, for each checked exception that can result from execution of the body of a method or constructor, a compile-time error occurs unless its exception type or a supertype of its exception type is mentioned in a throws clause in the declaration of the method or constructor.本质上,对于可能由方法体或构造函数的执行导致的每个已检查异常,除非在方法声明的 throws 子句中提及其异常类型或其异常类型的超类型,否则会发生编译时错误或构造函数。

This doesn't say you must throw the given checked exception within the method body.这并不是说您必须在方法主体中抛出给定的已检查异常。 Note that you can use throws with unchecked exceptions, but this has no effect on the program, as unchecked exceptions may be thrown anywhere without being handled.请注意,您可以对未经检查的异常使用throws ,但这对程序没有影响,因为未经检查的异常可能会在任何地方抛出而无需处理。 That's the point of them.这就是他们的重点。

In your code, you throw a RuntimeException .在您的代码中,您抛出一个RuntimeException Any class extending RuntimeException (including itself) is unchecked by definition.根据定义,任何扩展RuntimeException类(包括它自己)都是未经检查的。 ArithmeticException is one of these, so you may assign it to a variable of type RuntimeException and then throw it without specifying it in the throws clause. ArithmeticException就是其中之一,因此您可以将其分配给RuntimeException类型的变量,然后将其抛出,而无需在throws子句中指定它。

For your second question, I'll assume that the compiler doesn't optimise away the various catch clauses.对于您的第二个问题,我假设编译器不会优化掉各种catch子句。 In that case, no, the catch which is executed is not determined at compile time.在这种情况下,不,执行的catch不是在编译时确定的。 When any exception is thrown in your program, it propagates up the stack until it is caught.当您的程序中抛出任何异常时,它会向上传播堆栈直到被捕获。 If it isn't, it halts execution and the stack trace is printed to System.err .如果不是,它会停止执行并将堆栈跟踪打印到System.err Since an ArithmeticException is thrown, the first catch clause does not match but the second one does, so is executed.由于抛出ArithmeticException ,第一个catch子句不匹配,但第二个匹配,因此被执行。 The third one ( catch (Exception e) ) would match, but order matters with catch clauses and only one is executed, so that clause is not executed here.第三个( catch (Exception e) )将匹配,但顺序与catch子句有关,并且只执行一个,因此此处不执行该子句。

However, in this case, it is not inconceivable that the compiler optimises away your catch clauses and directs the program straight to the code in the catch (ArithmeticException e) clause, as your method will always throw ArithmeticException .但是,在这种情况下,编译器优化掉您的catch子句并将程序直接定向到catch (ArithmeticException e)子句中的代码并非不可想象,因为您的方法将始终抛出ArithmeticException It must be considered, however, that any line of code may throw some obscure error like OutOfMemoryError ;然而,必须考虑到,任何一行代码都可能抛出一些模糊的错误,比如OutOfMemoryError the compiler must allow for such edge cases when optimising.编译器在优化时必须考虑到这种边缘情况。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM