java 栈 返回值_如何在finally块中访问返回值

本文探讨了在Java中如何在finally块中访问方法返回值的问题,提供了一种通过设置中间变量并在finally块中检查的技巧,同时讨论了其他可能的解决方案,如额外的方法调用和可读性更强的代码结构。

如何在finally块中访问返回值

Published:

11 Jun 2015

Category:

尽管JVM是基于栈的虚拟机,但Java语言却不允许你去访问这个栈。但其实在某些场景下(尽管是不太常见),这个功能是非常实用的。

示例

方法返回的结果会存储在栈上。看下这段代码:

public int method() {

if (something)

return 1;

...

if (somethingElse)

return 2;

...

return 0;

}

如果我们不考虑[停机问题](http://it.deepinmind.com/%5BHalting%20problem%5D(http://en.wikipedia.org/wiki/Halting_problem),错误处理,以及其它学术上的问题,可以这么说,上述方法“肯定”会返回0,1或者2。并且这个值会存储在栈上,然后才会跳出这个方法。

有时候还会有这么一种情况,就是希望在返回某个特定值的时候执行特定的操作。大家可能又会为 该不该使用多重return语句陷入无止境的口水仗了,这个方法就会变成这样:

public int method() {

int result = 0;

if (something)

result = 1;

...

if (somethingElse)

result = 2;

...

// Important action here prior to return

if (result == 1337)

log.info("hehehe ;-)");

return result;

}

当然了,上面的方法是有问题的,因为如果if (something) return 1 执行了,那么 if (something) return 2就不会被执行了。为了能达到原来“单一return语句”那样的效果,我们得把代码重写成这样:

public int method() {

int result = 0;

if (something)

result = 1;

else {

...

if (somethingElse)

result = 2;

else {

...

}

}

// Important action here prior to return

if (result == 1337)

log.info("hehehe ;-)");

return result;

}

当然了,关于这个方法 是否应该使用大括号以及缩进级别 还可以再吵上几天,不过这只是空费唇舌而已。

从栈中获取返回结果

其实我们想做的事情就是在原来的实现中,在返回结果之前的时候,检查下栈内的结果是什么,下面是用Java写的伪代码:

public int method() {

try {

if (something)

return 1;

...

if (somethingElse)

return 2;

...

return 0;

}

// Important action here prior to return

finally {

if (reflectionMagic.methodResult == 1337)

log.info("hehehe ;-)");

}

}

好消息就是,这个确实能实现!一个简单的小技巧就能实现这个功能:

public int method() {

int result = 0;

try {

if (something)

return result = 1;

...

if (somethingElse)

return result = 2;

...

return result = 0;

}

// Important action here prior to return

finally {

if (result == 1337)

log.info("hehehe ;-)");

}

}

不过坏消息就是,你可千万别忘了给返回值赋值啊。不过不管怎么说,这项技术还是挺有用的,它可以实现“方法栈访问”,尽管Java语言并不允许我们这么做。

当然了

不过,当然你还可以通过下面这种方式来解决,虽然有点烦人:

public int method() {

int result = actualMethod();

if (result == 1337)

log.info("hehehe ;-)");

return result;

}

public int actualMethod() {

if (something)

return result = 1;

...

if (somethingElse)

return result = 2;

...

return result = 0;

}

在很多时候,这种方案的确是要更好一些(可读性更强)。不过有时候可能你想要在finally块中做的并不止是打印日志这么简单,又或者你想访问的也不止是result的值,而你又不想再重构这个方法,这时候这项技巧就派上用场了。

还有别的方法吗

现在该看你的了。你有什么推荐的可选方案吗?比如说,使用try monad,或者是切面?

### 在 Java 异常处理中,如何在 `finally` 中终止程序或退出 在 Java 的异常处理机制中,`finally` 用于执行无论是否发生异常都必须完成的操作,例如资源释放等。然而,在某些特殊情况下,可能需要在 `finally` 中强制终止程序或提前退出。 #### 使用 `System.exit(int)` 终止程序 Java 提供了 `System.exit(int)` 方法来直接终止当前运行的 JVM。该方法接受一个整数参数作为状态码,通常非零表示异常终止。如果在 `catch` 或 `finally` 中调用此方法,则会立即结束程序,不再继续执行后续代码[^2]。 ```java try { // 可能抛出异常的代码 } catch (ArithmeticException e) { System.out.println("捕获到算术异常"); System.exit(1); // 立即终止程序 } finally { System.out.println("这段代码不会被执行"); } ``` 在这种情况下,`finally` 中的代码将不会执行,因为 `System.exit()` 会强制 JVM 终止。 #### 使用 `return` 提前退出 `finally` 尽管 `finally` 通常用于清理操作,但它也支持使用 `return` 语句提前退出该。需要注意的是,如果 `finally` 中存在 `return`,它将覆盖 `try` 或 `catch` 中的返回值,导致实际返回值被替换为 `finally` 中的。 ```java public static int test() { try { return 1; } finally { return 2; // 最终返回值变为2 } } ``` 这种做法可能导致逻辑混乱,因此应谨慎使用。 #### 使用 `break` 或 `continue`(仅限循环结构) 虽然 `break` 和 `continue` 可以控制流程,但它们只能在 `finally` 内部包含循环结构时发挥作用。若 `finally` 中没有循环,这两个关键字将无法影响程序流。 ```java try { // 某些操作 } finally { for (int i = 0; i < 1; i++) { break; // 仅在循环内有效 } System.out.println("继续执行清理工作"); } ``` #### 特殊注意事项 - **避免滥用 `System.exit()`**:由于其会立即终止程序,可能导致资源未正确释放或日志信息丢失。 - **慎用 `return`**:尤其是在有返回值的方法中,`finally` 内的 `return` 会掩盖原始返回值,造成调试困难。 - **确保资源释放**:即使在 `finally` 中进行强制退出,也应尽量保证必要的资源关闭逻辑已完成。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值