Java 异常中嵌套finally的行为

Java 异常中嵌套finally的行为,java,Java,今天在工作中,我不得不回顾一段与这个模拟示例类似的代码片段 包装试验 import java.io.IOException; import org.apache.log4j.Logger; public class ExceptionTester { public static Logger logger = Logger.getLogger(ExceptionTester.class); public void test() throws IOException { n

今天在工作中,我不得不回顾一段与这个模拟示例类似的代码片段

包装试验

import java.io.IOException;
import org.apache.log4j.Logger;

public class ExceptionTester {

    public static Logger logger = Logger.getLogger(ExceptionTester.class);

public void test() throws IOException {
    new IOException();
}

public static void main(String[] args) {
    ExceptionTester comparator = new ExceptionTester();
    try {
        try {
            comparator.test();
        } finally {
            System.out.println("Finally 1");
        }
    } catch(IOException ex) {
        logger.error("Exception happened" ex);
            // also close opened resources
    } 
    System.out.println("Exiting out of the program");
}
}

它正在打印以下输出。我预期会出现编译错误,因为内部try没有catch块


我不明白为什么IOException被外部catch块捕获。如果有人能解释这一点,我将不胜感激,特别是引用堆栈展开过程,我认为问题在于您的函数

public void test() throws IOException {
    new IOException();
}
实际上不会引发异常-它只是创建一个新的IOException对象。将此更改为

public void test() throws IOException {
    throw new IOException();
}

应该解决这个问题。

我认为问题在于您的函数

public void test() throws IOException {
    new IOException();
}
实际上不会引发异常-它只是创建一个新的IOException对象。将此更改为

public void test() throws IOException {
    throw new IOException();
}

应该解决这个问题。

finally块表示在正常和异常条件下都必须完成的任务

你带面试候选人去吃午饭。午餐时,你发现他因谋杀被警方通缉。例外午餐结束了,面试完全失败了,但是。。。你还得付午餐费

try {
    meetForLunch(interviewCandidate);
}
finally {
    lunchBill.pay();
}
请注意,支付午餐费用并没有考虑到例外情况,你仍然需要在面试中对凶手采取一些措施。这只是一个松散的一端,必须在处理损坏控制之前加以处理

大多数finally块都是这样使用的:无论您是否成功保存数据,都需要关闭文件;无论事务是否被批准,都需要关闭数据库连接,等等

异常继续以其愉快的方式向外扩展,在封闭范围中查找匹配的catch块


请注意,除非进程在try块仍在执行时结束,否则finally块将始终运行。

finally块表示必须在正常和异常条件下完成的任务

你带面试候选人去吃午饭。午餐时,你发现他因谋杀被警方通缉。例外午餐结束了,面试完全失败了,但是。。。你还得付午餐费

try {
    meetForLunch(interviewCandidate);
}
finally {
    lunchBill.pay();
}
请注意,支付午餐费用并没有考虑到例外情况,你仍然需要在面试中对凶手采取一些措施。这只是一个松散的一端,必须在处理损坏控制之前加以处理

大多数finally块都是这样使用的:无论您是否成功保存数据,都需要关闭文件;无论事务是否被批准,都需要关闭数据库连接,等等

异常继续以其愉快的方式向外扩展,在封闭范围中查找匹配的catch块

请注意,除非进程在try块仍在执行时结束,否则finally块将始终运行。

上面的代码不需要太多解释-不一定涉及调用堆栈!。你的困惑是什么?我错过什么了吗? 这是我的解释

第一点

你不需要既抓又抓 最后一个街区。你可以喝一杯 他们或他们两个都有一个 试着用block,但不要一个也不试。 finally子句中的代码 将始终执行,即使 异常是从 试着抓住那个块。如果你的代码 try或try语句中的return语句 catch块中的代码 最后,将执行该块 在从方法返回之前。 因此,在上面的代码中,从未抛出异常,因为您没有在测试方法中使用throw 然而,最终块按照语言规范的承诺执行,您最终得到了输出1。执行序列中的下一条语句是System.out.PrintLExit of The program;因为没有异常,所以从未到达catch块。因此,退出程序是打印出来的。

上面的代码不需要太多解释-不一定涉及调用堆栈!。你的困惑是什么?我错过什么了吗? 这是我的解释

第一点

你不需要既抓又抓 最后一个街区。你可以喝一杯 他们或他们两个都有一个 试着用block,但不要一个也不试。 finally子句中的代码 将始终执行,即使 异常是从 试着抓住那个块。如果你的代码 try或try语句中的return语句 catch块中的代码 最后,将执行该块 在从方法返回之前。 因此,在上面的代码中,从未抛出异常,因为您没有在测试方法中使用throw
然而,最终块按照语言规范的承诺执行,您最终得到了输出1。执行序列中的下一条语句是System.out.PrintLExit of The program;因为没有异常,所以从未到达catch块。因此,将打印退出程序。

这就是为什么未打印“发生异常”的原因,但它与最终块无关。这就是为什么未打印“发生异常”
ed,但它与finally块无关。try必须具有>=1个catch和/或finally。捕获不是必需的。一次尝试必须有>=1个捕获和/或一个finally。当然,如果候选人在午餐时谋杀了你,这个类比就不成立了-@斯蒂芬:我想你错过了最后一句话。@Ben Voight-就餐厅而言,这个过程还没有结束。@Stephen:餐厅将不得不启动恢复程序。@Stephen:如果你死了,最后一个街区就不会运行了。然后,餐厅必须检测与客户失去的联系,正如我所评论的那样,启动对凶手、遗产或雇主的追偿程序,因为这是一次商务旅行。在编程世界中,当客户端进程死亡时,数据库必须处理废弃的事务。当然,如果候选人在午餐时谋杀了你,这种类比就不成立了-@斯蒂芬:我想你错过了最后一句话。@Ben Voight-就餐厅而言,这个过程还没有结束。@Stephen:餐厅将不得不启动恢复程序。@Stephen:如果你死了,最后一个街区就不会运行了。然后,餐厅必须检测与客户失去的联系,正如我所评论的那样,启动对凶手、遗产或雇主的追偿程序,因为这是一次商务旅行。在编程世界中,当客户端进程死亡时,数据库必须处理废弃的事务。