简体   繁体   English

最终投掷之间的区别

[英]Difference between throw and throws in finally

I am preparing for OCP exam and I'm using Enthuware . 我正在准备OCP考试,并且正在使用Enthuware I got this question, what is the result of compiling and running the following code? 我得到了这个问题,编译并运行以下代码是什么结果?

try {
    throw new IOException();
} catch(IOException e) {
    throw e;
} finally {
    throw new RuntimeException();
}

Obviously, the code does compile but it throws a RuntimeException and I totally understand why. 显然,代码确实可以编译,但是会抛出RuntimeException ,我完全理解为什么。 I'm just curious why the following code doesn't compile: 我很好奇为什么以下代码无法编译:

try {
    throw new IOException();
} catch(IOException e) {
    throw e;
} finally {
    test();
}

Where test() function looks like: test()函数如下所示:

static final void test() throws RuntimeException {
    throw new RuntimeException();
}

Even though I declared test function as final because I thought that it might the compiler is aware of overriding ... 即使我将test功能声明为final功能,是因为我认为编译器可能会意识到覆盖 ...

Could someone please explain it to me? 有人可以给我解释一下吗?

Sorry for bad English! 对不起,英语不好!

-- Edit: Just wondering why down-vote? - 编辑:只是想知道为什么要投票?

Error message is compile error: 错误消息是编译错误:

Unhandled exception type IOException 未处理的异常类型IOException

And the error message when I tried to compile it is: 当我尝试编译它时,错误消息是:

Exception in thread "main" java.lang.Error: Unresolved compilation problem: Unhandled exception type IOException 线程“主”中的异常java.lang.Error:未解决的编译问题:未处理的异常类型IOException

The first snippet compiles because the finally block runs before a value is returned or an exception thrown from the non- finally part of the method. 之所以编译第一个代码段,是因为finally返回值或从方法的非finally部分抛出异常之前运行。 The fact that you're throwing a RuntimeException means that you won't be throwing the IOException that you otherwise would. 您抛出RuntimeException的事实意味着您将不会抛出IOException ,否则将抛出该IOException The compiler can work this out, and it therefore doesn't insist that you either declare or catch the IOException . 编译器可以解决此问题,因此它不坚持要求您声明或捕获IOException

But the compiler only looks at one method at a time when it's performing this check. 但是编译器在执行此检查时一次只查看一种方法。 So the second snippet fails to compile, because the compiler doesn't check whether test() will always throw the RuntimeException . 因此,第二个代码段无法编译,因为编译器没有检查test()是否总是抛出RuntimeException Instead, it assumes that test() might not throw the RuntimeException ; 相反,它假定test()可能不会抛出RuntimeException and if that were to happen, the IOException would be thrown. 如果发生这种情况,将抛出IOException Therefore, the compiler insists that you either catch that IOException , or declare it in a throws clause. 因此,编译器坚持要求您要么捕获该IOException ,要么在throws子句中声明它。

In java Exception handling have concept Exception propagation. 在Java中,异常处理具有异常传播的概念。

An exception is first thrown from the top of the stack and if it is not caught, it drops down the call stack to the previous method, if not caught there, the exception again drops down to the previous method, and so on until they are caught or until they reach the very bottom of the call stack. 首先从栈顶抛出一个异常,如果未捕获到异常,它将调用堆栈降到前一个方法,如果未捕获到那里,则异常再次下降到前一个方法,依此类推,直到被捕获为止。被捕获或直到它们到达调用堆栈的最底端。 This is called exception propagation. 这称为异常传播。

Rule 1: By default, Unchecked Exceptions are forwarded in calling chain (propagated). 规则1:默认情况下,未经检查的异常会在调用链中传播(传播)。

Rule 2: By default, Checked Exceptions are not forwarded in calling chain (propagated). 规则2:默认情况下,检查异常不在调用链中传播(传播)。

try {
    throw new IOException();
} catch(IOException e) {
    throw e;
} finally {
    throw new RuntimeException();
}

In above code snippet it's the throwing of the RuntimeException that prevents the throwing of the IOException. 在上面的代码片段中,抛出RuntimeException阻止了IOException的抛出。

try {
    throw new IOException();
} catch(IOException e) {
    throw e;
} finally {
    test();
}
static final void test() throws RuntimeException {
    throw new RuntimeException();
}

In above code snippet test() method throwing of the RuntimeException but not prevents the throwing of the IOException. 在上面的代码中,test()方法抛出RuntimeException,但并不能阻止IOException的抛出。 As by Rule 2 by default compiler doesn't propagate the Checked Exceptions so for that you have to declare or handle the exception. 规则2一样 ,默认情况下,编译器不会传播Checked Exceptions,因此您必须声明或处理该异常。

Lets take example if you replace IOException with RuntimeException then it will not give compiletime error because by Rule 1 by default unchecked Exceptions are forwarded in calling chain (propagated). 让我们举个例子,如果用RuntimeException替换IOException ,那么它将不会产生编译时错误,因为默认情况下,根据规则1 ,未经检查的异常会在调用链中传播(传播)。

try {
    throw new RuntimeException();
} catch(RuntimeException e) {
    throw e;
} finally {
    test();
}
static final void test() throws RuntimeException{
    throw new RuntimeException();
}

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

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