【Java报错】记录一次调用递归方法导致的 StackOverFlowError 及如何重构递归代码避免栈溢出
1. 递归方法
以下代码为核心代码,省略了不必要的业务流程,用来说明问题:
private boolean getRecommendListAndMatch(String newCycleEndDateStr, String tag) {boolean isMatchSuccess = false;// 获取数据BaseResult recommendList = dataMatchService.getRecommendListByPara();// 数据处理assert recommendList != null;if (recommendList.data.total > 0) {// 比较复杂的业务流程isMatchSuccess = true;} else {log.info("结束时间:{} 内无符合条件的数据!", newCycleEndDateStr);}// 递归调用方法if (isMatchSuccess) {getRecommendListAndMatch(newCycleEndDateStr, tag);}return isMatchSuccess;}
在网上找了几张图片:
这是一个很典型的递归调用
栈是一种比较简单的数据结构,具有后进先出
的特性。
栈本身是一个线性表,但是在这个表中只有一端允许数据的进出。那为什么方法要放在栈结构内呢
?比如方法A调用方法B,方法A的栈帧要先入栈(A的方法体和参数都要保存到B方法调用结束,否则B方法用的A里的参数就会出现空指针了)然后入栈B方法的数据,B方法调用结束,B方法的栈帧被弹出,此时如果A方法不再调用其他方法,A方法执行完了之后也会被弹出。
可想而知,如果递归方法的参数、对象较多再加上递归层数较多时,栈的空间毕竟是有限的,溢出就不足为奇了。
2. 重构代码
重构递归方法的逻辑不复杂,这里提供一种,使用 do while 实现递归逻辑:
// 1. 调用条件boolean isMatchSuccess;do {// 2. 修改调用条件isMatchSuccess = getRecommendListAndMatch(newCycleEndDateStr, tag);// 3. 判断调用条件是否成立} while (isMatchSuccess);
三个点:
- 判断是否再次调用的条件
- do方法体里对调用条件的处理
- while再次判断调用条件
主方法的调整(删掉递归调用):
private boolean getRecommendListAndMatch(String newCycleEndDateStr, String tag) {boolean isMatchSuccess = false;// 获取数据BaseResult recommendList = dataMatchService.getRecommendListByPara();// 数据处理assert recommendList != null;if (recommendList.data.total > 0) {// 比较复杂的业务流程isMatchSuccess = true;} else {log.info("结束时间:{} 内无符合条件的数据!", newCycleEndDateStr);}return isMatchSuccess;}
重构后,每次调用结束,方法帧都会从栈内弹出,从而避免了长时间过度占用栈空间的问题。
【Java报错】记录一次调用递归方法导致的 StackOverFlowError 及如何重构递归代码避免栈溢出相关推荐
- Errors报错记录
Errors报错记录 前言 Error1 Error2 Error3 Error4 Error5 Error6 Error7 Error8 Error9 Error10 Error11 总结 前言 记 ...
- 【jenkins打包maven项目报错记录】
jenkins打包maven项目报错记录 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3 ...
- Structured Streaming报错记录:Overloaded method foreachBatch with alternatives
Structured Streaming报错记录:Overloaded method foreachBatch with alternatives [文章目录] Structured Streamin ...
- 【VINS-Mono】RealsenseD435i运行VINS-Mono,在ubuntu18.04和opencv3和cv_bridge的报错记录
VINS-Mono(A Robust and Versatile Monocular Visual-Inertial State Estimator) https://github.com/HKUST ...
- win10安装MySQL数据库和MyServer数据库及其报错记录
锚点: Win10装MySQL数据库及报错记录 Win10装MySever数据库及报错记录 <----------------分 隔 符----------------> Win10装My ...
- java报错MalformedURLException: unknown protocol: c
java报错:MalformedURLException: unknown protocol: c 1. 报错情况: 部分代码: //打开图片path="C:/Users/MyUser/im ...
- oracle 被另一用户锁定,Oracle报错记录被另外一个用户锁定的解决方案
原因 当一个用户对数据进行修改时,若没有进行提交或者回滚,Oracle不允许其他用户修改该条数据,在这种情况下修改,就会出现:"记录被另外一个用户锁定"错误. 解决 查询用户.数据 ...
- java报错-找不到或无法加载主类(Error: Could not find or load main class)
此文首发于我的个人博客:java报错-找不到或无法加载主类(Error Could not find or load main class) - zhang0peter的个人博客 比如说test.ja ...
- php curl 不验证ssl,PHP Curl https跳过ssl证书认证报错记录及解决
PHP Curl https跳过ssl证书认证报错记录及解决 function get($url = '', $cookie = '') { $ch = curl_init(); curl_setop ...
最新文章
- shell 获取ora报错信息_频发:故障排除之又见 ORA-4031丨云和恩墨技术通讯
- Android深度探索读书笔记 第七章
- 框架应用 : Spring MVC - 开发详述
- CentOS上安装Python3.7.4
- ecs使用脚本安装oracle
- uniapp 仿钉钉考勤统计页面的日历组件,通过日历展示每日考勤打卡情况,支持在日历上打两种不同类型的点,大致适配各种分辨率
- java中quickhit_关于java的QuickHit打字游戏小项目
- 【Flink】flink-1.12 通过 -t 指定模式后无法指定yarn参数
- ArcGIS10.8版本的下载安装及其注意事项
- vue下用canvas实现图片标注工具,允许图片放大、缩小,允许拖拽图片
- arm开发板挂载win10和ubuntu haneWIN NFS Server
- java application.doevents_Application.DoEvents()笔记
- 计算机考研各省份学校,想考研究生,哪个省份的高校更容易考上?
- C# Panel半透明
- 划重点 2022面试必刷461道大厂架构面试真题汇总+面经+简历模板
- Vue 组件之间传值
- 涨分神器-基于PPYOLOE的切图和拼图解决方案
- Follow My Heart Of Jan.Feb.Mar. 2023
- 手机屏幕显示正常但是触摸有一部分出问题,是内屏坏了吗?保修期内手机该不该走官方售后?
- 关系型数据库中的关键字、主关键字和候选关键字
热门文章
- 【转】windows Server2012安装iis
- HOWTO:如何在代码中获取安装包目标机上的Windows Installer(MSI)版本
- DataGrid 完全攻略之二(把数据导出到Excel)
- linux 脚本 if else,基于shell的if和else详解
- mysql获取用户名_mysql-LEFT JOIN 3列获取用户名
- java中this的含义_Javascript中的this的含义
- css3 渐变色 3种,css3实现渐变色文字的三种方法
- Android Studio同步失败设置代理,Android Studio如何设置代理?
- mt4虚拟服务器在哪里看,mt4查看自己服务器地址
- 脚本必须位于html的,js 前端第三剑客