Java基础—递归方法

文章介绍了递归的概念,通过一个Java示例展示了递归调用的过程。当递归方法没有出口条件时会导致StackOverflowError。递归虽然可以使代码简洁,但消耗更多内存且深度大时易引发错误。相比之下,循环通常更快,但在处理特定问题如遍历目录时,递归更为合适。建议根据问题性质选择合适的方法。
摘要由CSDN通过智能技术生成

什么是递归

一个方法调用自己的方法,方法的递归调用可以重复执行一段代码,看完下面的例子,相信你对递归会有深入的了解:

package Class.Recursion;

public class Demo_Sum {
        public static void main(String[] args) {
            //求1-3的累加和
            int n = sum_recursion(1,3);
            System.out.println(n);
        }

        //实现数据区间的累加和方法
        public static int sum_recursion(int start,int end){
            //出口条件
            if (start == end) {
                return end;
            }
            //递归调用
            return start + sum_recursion(start+1,end);
        }
}

结果:
在这里插入图片描述
下边研究一下sum_recursion方法的递归执行流程,见下图:
在这里插入图片描述
步骤讲解:
1)main方法调用sum_recursion方法,传入1,3;

2)sum_recursion方法调用sum_recursion方法,传入2,3;

3)sum_recursion方法调用sum_recursion方法,传入3,3;

4)sum_recursion方法判断start等于end,返回3给上个调用者;

5)sum_recursion方法返回2+3给上个调用者;

6)sum_recursion方法返回1+2+3给main方法。

我们发现方法的递归调用和方法之间的调用流程是一样,只不过递归调用是调用自己。

如果sum_recursion方法中没有下边的语句将会有什么结果:在这里插入图片描述
StackOverflowError表示“栈溢出”错误。
为什么递归方法调用会抛出StackOverflowError栈溢出错误呢?下面我们分析这个问题,首先我们来了解一下执行方法的原理:

栈帧

每次执行一个方法会在JVM栈中开辟一块内存,用于存放执行方法所需要的数据,比如方法的局部变量、对象引用等 ,这块内存叫栈帧。JVM栈是JVM运行时内存的一个区域,JVM运行时内存还包括堆、方法区、程序计数器等区域。

:是一种数据结构,具有后进先出的特点,下面引用百度百科的栈的模型图来说明栈的特点:
321
对栈的操作包括入栈(也叫压栈)和出栈(也叫弹栈)两个。

入栈是将数据压到栈顶,如上图,首先将a1压入栈,再将a2压入栈,直到将an压入栈,最上边位置叫栈顶,最下边的是栈底,上图an为栈顶元素,a1为栈底元素。

出栈是将数据从栈中弹出,出栈是要弹出的栈顶的元素。

所以,栈的特点是后进先出,先进后出,如上图,an最后入栈,却最先出栈,a1最先入栈却最后出栈。

理解了栈的特点,我们再结合JVM栈和方法执行过程,对应的栈内存结构的变化过程如下:
在这里插入图片描述

压栈是每执行一次方法会创建一个栈帧,每一次的递归调用都会压栈。当方法执行完执行出栈。上述列子中从执行main方法开始,当start等于end时方法执行return 1,即执行方法的出口,此时出栈,直到执行完成main,main方法出栈,程序运行结束,见下图:
在这里插入图片描述
为什么方法递归调用会抛出StackOverflowError栈溢出错误呢?

当我们把方法的出口代码注释,递归调用将不停的在栈中创建栈帧,整个栈的深度会很大,如果超过了虚拟机要求的深度则报StackOverflowError错误。

所以对递归方法的定义一定要有递归方法的出口

选择使用递归还是循环?

一般情况下使用循环结构可以实现递归所实现的功能,只是有时候用递归写代码更明了,递归和循环结构有优劣分析如下:

递归:

优势:

1、代码结构简洁。

劣势:

1、耗费内存,每次调用需要开辟新的栈空间。

2、递归深度大会导致StackOverflowError。

循环结构:

优势:

1、速度快。

劣势:

1、有些场景单纯用循环结构不适合,比如:遍历磁盘中的所有目录及子目录中的所有文件,因为目录结构的复杂性用循环没有递归去遍历目录及子目录方便。

建议:能用循环解决的问题优先用循环解决,适合递归的场景要用递归解决。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值