本文共 2011 字,大约阅读时间需要 6 分钟。
在编程中,finally
语句的执行机制是关键,当 try
或 catch
块中遇到异常或正常返回时,finally
块都会执行,除非在代码中使用 System.exit(0)
。以下是几点需要注意的:
一般情况下的执行:当 try
块正常执行时,返回值传回调用者,或者抛出异常进入 catch
块时,finally
块会在异常处理或正常返回后被执行。
不执行的情况:唯一的例外是当代码中直接调用 System.exit(0)
,这种情况下 JVM 会立即终止执行流程,导致 finally
语句无法执行。
例如,在以下代码中:
public class Demo8 { public static void main(String[] args) { haha(); } public static void haha() { try { int a = 10; int b = 0; System.out.println(a / b); } catch (Exception e) { // 退出JVM System.out.println("出现异常"); System.exit(0); // 唯一导致 finally 不执行的情况 // 参数0表示正常退出,非零表示非正常退出 } finally { System.out.println("xxxxxxxxxx"); } }}
当 haha()
调用 System.out.println(a / b)
时,由于除法为零会抛出 ArithmeticException
,进入 catch
块。然后执行 System.exit(0)
,导致程序退出,而 finally
块不会执行。
在以下代码中:
public static void main(String[] args) { int a = haha(); System.out.println(a);}public static int haha() { try { int a = 10; return a; } catch (Exception e) { } finally { a = 20; } return 0;}
分析:在 haha()
方法中,try
块不抛出异常,直接在 try
内返回 a
。此时,因为 try
块没有异常,finally
块会在返回前被执行。finally
块中修改 a
,但 a
是在 try
块中定义的变量。由于Java允许在非异常情况下进行一次返回,而 finally
在返回前会执行,所以无论返回时的 a
引用如何,最终返回的值都将是 try
中最初的 a
值,即 10。
在以下代码中:
public static void main(String[] args) { Person p = haha(); System.out.println(p.age);}public static Person haha() { try { Person p = new Person(); p.age = 18; return p; } catch (Exception e) { return null; } finally { p.age = 28; }}static class Person { int age;}
分析:由于 Person
是一个引用类型,haha()
方法返回的是对象 p
的引用。当 try
块结束后,finally
块会在返回前修改 p.age
。虽然 try
块中创建了 p
对象,并将其赋值给调用者,但 finally
块修改的是堆中的对象 p
,而不仅仅是栈中的引用。因此,当调用者访问 p.age
时,其值将是 28,而不是 try
块中的 18。
finally
语句修改的是堆中的对象数据,因此即使返回了引用,对象的内存也已经被修改过。这些知识点突显了基本类型值的传递和返回方式的区别,以及 finally
语句执行机制对于不同数据类型的影响。
转载地址:http://rjagz.baihongyu.com/