try、catch、finally、throw、throws 的用法,finally 块一定会执行吗?举反例说明。

54 阅读3分钟

在 Java 中,​​try​​​、​​catch​​​、​​finally​​​、​​throw​​​、​​throws​​​ 是异常处理的核心关键字,各自有明确的用途,具体用法和 ​​finally​​ 块的执行情况如下:

一、关键字用法

用于包裹可能发生异常的代码块,是异常处理的起点。​​try​​ 块必须与 ​​catch​​ 或 ​​finally​​ 结合使用(至少出现一个)。

示例: ​​java try { // 可能抛出异常的代码(如文件操作、类型转换等) int result = 10 / 0; } catch (ArithmeticException e) { // 处理异常 } ​

  1. ​​​catch​​​

用于捕获并处理 ​​try​​ 块中抛出的异常,紧跟在 ​​try​​ 之后。可以有多个 ​​catch​​ 块处理不同类型的异常(子类异常需放在父类异常前)。

示例: ​​java try { // 可能抛出异常的代码 } catch (NullPointerException e) { System.out.println("空指针异常"); } catch (IndexOutOfBoundsException e) { System.out.println("索引越界异常"); } ​

  1. ​​​finally​​​

用于定义无论是否发生异常都需要执行的代码(如资源释放),紧跟在 ​​catch​​ 块之后(若没有 ​​catch​​,则直接跟在 ​​try​​ 后)。

示例: ​​java FileReader fr = null; try { fr = new FileReader("file.txt"); } catch (FileNotFoundException e) { e.printStackTrace(); } finally { // 确保资源关闭 if (fr != null) { try { fr.close(); } catch (IOException e) { e.printStackTrace(); } } } ​

  1. ​​​throw​​​

用于在方法内部主动抛出一个具体的异常对象(手动触发异常)。 示例: ​​java public void checkAge(int age) { if (age < 0) { // 主动抛出非法参数异常 throw new IllegalArgumentException("年龄不能为负数"); } } ​

  1. ​​​throws​​​

用于在方法声明处声明该方法可能抛出的异常类型(告知调用者需处理这些异常),多个异常用逗号分隔。 示例: ​​java // 声明方法可能抛出 IO 异常 public void readFile() throws IOException { FileReader fr = new FileReader("file.txt"); fr.close(); } ​

二、​​finally​​ 块一定会执行吗?

不一定。​​finally​​ 块的执行依赖于 JVM 正常运行,若在 ​​try​​ 或 ​​catch​​ 块中发生导致 JVM 终止的操作,​​finally​​ 块将不执行。

反例 1:​​System.exit(0)​​ 终止 JVM

​java try { System.out.println("try 块执行"); System.exit(0); // 终止 JVM } catch (Exception e) { e.printStackTrace(); } finally { System.out.println("finally 块执行"); // 不会执行 } ​

说明:​​System.exit(0)​​ 会直接终止当前 JVM 进程,程序停止运行,​​finally​​ 块无法执行。

反例 2:线程被强制终止 ​​java public static void main(String[] args) { Thread t = new Thread(() -> { try { System.out.println("线程 try 块"); Thread.sleep(1000); // 模拟耗时操作 } catch (InterruptedException e) { e.printStackTrace(); } finally { System.out.println("线程 finally 块"); // 可能不执行 } }); t.start(); t.interrupt(); // 中断线程(若在 finally 执行前生效) // 极端情况:调用 t.stop()(已过时,但强制终止线程时 finally 可能不执行) } ​

说明:若线程在 ​​finally​​ 块执行前被强制终止(如 ​​stop()​​ 方法,或中断导致无法继续执行),​​finally​​ 块可能不执行。

其他特殊情况
  • 虚拟机崩溃(如内存溢出 ​​OutOfMemoryError​​ 导致 JVM 异常终止)。
  • 硬件故障(如断电、CPU 故障)。

这些情况都会导致程序无法继续运行,​​finally​​ 块自然不会执行。

总结

  • ​try​​/​​catch​​/​​finally​​ 用于捕获和处理异常,​​throw​​ 手动抛异常,​​throws​​ 声明方法可能抛的异常。
  • ​finally​​ 块大多数情况会执行(如正常流程、异常被捕获、​​return​​/​​break​​ 等),但在 JVM 终止或线程被强制终止等极端情况下不执行