热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

如何在finally块中访问返回值

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

尽管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学习笔记之面向对象编程(OOP)
    本文介绍了Java学习笔记中的面向对象编程(OOP)内容,包括OOP的三大特性(封装、继承、多态)和五大原则(单一职责原则、开放封闭原则、里式替换原则、依赖倒置原则)。通过学习OOP,可以提高代码复用性、拓展性和安全性。 ... [详细]
  • Java太阳系小游戏分析和源码详解
    本文介绍了一个基于Java的太阳系小游戏的分析和源码详解。通过对面向对象的知识的学习和实践,作者实现了太阳系各行星绕太阳转的效果。文章详细介绍了游戏的设计思路和源码结构,包括工具类、常量、图片加载、面板等。通过这个小游戏的制作,读者可以巩固和应用所学的知识,如类的继承、方法的重载与重写、多态和封装等。 ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • 本文介绍了Java工具类库Hutool,该工具包封装了对文件、流、加密解密、转码、正则、线程、XML等JDK方法的封装,并提供了各种Util工具类。同时,还介绍了Hutool的组件,包括动态代理、布隆过滤、缓存、定时任务等功能。该工具包可以简化Java代码,提高开发效率。 ... [详细]
  • 如何使用Java获取服务器硬件信息和磁盘负载率
    本文介绍了使用Java编程语言获取服务器硬件信息和磁盘负载率的方法。首先在远程服务器上搭建一个支持服务端语言的HTTP服务,并获取服务器的磁盘信息,并将结果输出。然后在本地使用JS编写一个AJAX脚本,远程请求服务端的程序,得到结果并展示给用户。其中还介绍了如何提取硬盘序列号的方法。 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • JVM 学习总结(三)——对象存活判定算法的两种实现
    本文介绍了垃圾收集器在回收堆内存前确定对象存活的两种算法:引用计数算法和可达性分析算法。引用计数算法通过计数器判定对象是否存活,虽然简单高效,但无法解决循环引用的问题;可达性分析算法通过判断对象是否可达来确定存活对象,是主流的Java虚拟机内存管理算法。 ... [详细]
  • 本文详细介绍了Java中vector的使用方法和相关知识,包括vector类的功能、构造方法和使用注意事项。通过使用vector类,可以方便地实现动态数组的功能,并且可以随意插入不同类型的对象,进行查找、插入和删除操作。这篇文章对于需要频繁进行查找、插入和删除操作的情况下,使用vector类是一个很好的选择。 ... [详细]
  • 闭包一直是Java社区中争论不断的话题,很多语言都支持闭包这个语言特性,闭包定义了一个依赖于外部环境的自由变量的函数,这个函数能够访问外部环境的变量。本文以JavaScript的一个闭包为例,介绍了闭包的定义和特性。 ... [详细]
  • 先看官方文档TheJavaTutorialshavebeenwrittenforJDK8.Examplesandpracticesdescribedinthispagedontta ... [详细]
  • 基于Socket的多个客户端之间的聊天功能实现方法
    本文介绍了基于Socket的多个客户端之间实现聊天功能的方法,包括服务器端的实现和客户端的实现。服务器端通过每个用户的输出流向特定用户发送消息,而客户端通过输入流接收消息。同时,还介绍了相关的实体类和Socket的基本概念。 ... [详细]
  • 本文整理了Java面试中常见的问题及相关概念的解析,包括HashMap中为什么重写equals还要重写hashcode、map的分类和常见情况、final关键字的用法、Synchronized和lock的区别、volatile的介绍、Syncronized锁的作用、构造函数和构造函数重载的概念、方法覆盖和方法重载的区别、反射获取和设置对象私有字段的值的方法、通过反射创建对象的方式以及内部类的详解。 ... [详细]
  • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
  • 不同优化算法的比较分析及实验验证
    本文介绍了神经网络优化中常用的优化方法,包括学习率调整和梯度估计修正,并通过实验验证了不同优化算法的效果。实验结果表明,Adam算法在综合考虑学习率调整和梯度估计修正方面表现较好。该研究对于优化神经网络的训练过程具有指导意义。 ... [详细]
  • 关键词:Golang, Cookie, 跟踪位置, net/http/cookiejar, package main, golang.org/x/net/publicsuffix, io/ioutil, log, net/http, net/http/cookiejar ... [详细]
author-avatar
violalal_134
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有