JAVA基础之方法的递归调用

本文介绍了JAVA中方法的递归调用,包括递归的基本概念、满足的三个条件、解决的问题类型以及递归举例,如打印问题和阶乘计算。通过递归方法还讲解了如何求解斐波那契数列,强调了递归的重要规则,如边界条件和递归返回段。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、基本说明

递归调用就是在当前的函数中调用当前的函数并传给相应的参数,这是一个动作,这一动作是层层进行的,直到满足一般情况的的时候,才停止递归调用,开始从最后一个递归调用返回。

简单的说:递归就是方法自己调用自己,每次调用是传入不同的变量,递归有助于编程者解决复杂的问题,同时可以让代码变得整洁。

递归本质:程序调用自身的编程技巧叫做递归。

2、递归需要满足三个条件:

  1. 边界条件
  2. 递归前进段
  3. 递归返回段

当边界条件不满足时,递归前进;当边界条件满足时,递归返回。

3、递归能解决什么问题?

  • 各种数学问题:8皇后问题,汉诺塔,阶乘问题,迷宫问题,球和篮子的问题(google编程大赛)
  • 各种算法中也会使用到递归,比如快排,并归排序,二分查找,分治算法等。
  • 将用栈解决的问题--->递归代码比较简洁

4、递归举例

4.1打印问题

public class TestRecursion {
    public static void main(String[] args) {
        a a = new a();
        a.test(4);
    }
}

class a {
    public void test(int n) {
        if (n >2) {
            test(n - 1);
        }
        System.out.println("n=" + n);
    }
}

打印问题在JVM内存中的执行过程

 4.2阶乘问题

public class TestRecursion {
    public static void main(String[] args) {
        int res = a.factorial(5);
        System.out.println("res=" + res);
    }
}

class a {
    //阶乘问题
    public int factorial(int n) {
        if (n == 1) {
            return 1;
        } else {
            return factorial(n - 1) * n;
        }
    }

}



阶乘问题分析:

此题中,按照递归的三个条件来分析:
(1)边界条件:阶乘,乘到最后一个数,即1的时候,返回1,程序执行到底;
(2)递归前进段:当前的参数不等于1的时候,继续调用自身;
(3)递归返回段:从最大的数开始乘,如果当前参数是5,那么就是5*4,即5*(5-1),即n*(n-1)

 5、递归方法进阶练习(求斐波那契数)

请使用递归的方式求出斐波那契数1,1,2,3,5,8,13....

给你一个整数n,求出他的值是多少

思路分析

  1. 当n = 1 斐波那契数是       1
  2. 当n = 2斐波那契数是        1
  3. 当n >= 3 斐波那契数是前两个数的和
  4. 这里就是一个递归的思路

代码实现

public class TestRecursion {
    public static void main(String[] args) {
        T t1 = new T();
        System.out.println("当n=7 对应的斐波那契数=" + t1.fibonacci(7));
    }
}

class T {
    public int fibonacci(int n) {
        if (n >= 1) {
            if (n == 1 || n == 2) {
                return 1;
            } else {
                return fibonacci(n - 1) + fibonacci(n - 2);
            }
        } else {
            System.out.println("要求输入的n>=1的整数");
            return -1;
        }
    }

}

控制台输出结果:当n=7时,对应的斐波那契数= 13;

6、递归重要规则

  1. 执行一个方法时,就创建一个新的受保护的独立空间(栈空间)
  2. 方法的局部变量是独立的,不会相互影响,比如n变量
  3. 如果方法中使用的是引用类型变量(比如数组,对象),就会共享该引用类型的数据。
  4. 递归必须向退出递归的条件逼近,否则就是无限递归(龟死了)
  5. 当一个方法执行完毕,或者遇到return,就会返回,遵守谁调用,就将结果返回给谁,同时当方法执行完毕或者放回时,该方法也就执行完毕。
### Java递归调用的概述 在 Java 编程语言中,递归是指函数在其定义或实现过程中直接或间接地调用了自己。这种技术对于处理能够被自然划分为相似子问题的任务特别有效[^3]。 #### 递归的工作原理 每当一个递归方法被执行时,在 JVM 上下文中会创建一个新的栈帧来保存该次调用的状态信息,比如传递给它的参数以及内部使用的局部变量等。如果递归层次太深,则可能会超出虚拟机所能提供的最大栈深度限制,从而引发 `StackOverflowError` 错误[^1]。 ```java public class Factorial { public static long factorial(long number) { if (number <= 1) { // base case return 1; } else { // recursive step return number * factorial(number - 1); } } public static void main(String[] args) { try { System.out.println("Factorial of 5 is " + factorial(5)); } catch (Exception e) { System.err.println(e.getMessage()); } } } ``` 上述代码展示了如何通过递归来计算阶乘值。需要注意的是,这里设置了一个终止条件(即基本情形),这是为了避免无限循环并最终导致堆栈溢出的关键所在。 #### 防止堆栈溢出的方法 为了防止由于过度深入而引起的堆栈溢出: - **优化算法逻辑**:确保存在清晰明确的基础情况,并且每一次递归都能朝着基础情况进行简化。 - **采用尾递归转换**:虽然标准版 JDK 不支持自动将常规递归转化为更高效的尾递归形式,但在编写代码时可以手动调整为尾递归模式以减少中间状态的数量。 - **迭代替代方案**:有时可以通过改写程序使用显式的数据结构如队列或者栈来进行广度优先搜索(BFS)/深度优先搜索(DFS),以此代替隐含于递归之中的系统调用栈操作[^4]。 #### 自引用与类级别的递归调用注意事项 当涉及到对象之间的相互关联或者是自我复制的数据结构时,应当小心谨慎地管理这些关系以免造成意外的行为。例如,在声明数组或其他容器类型作为实例字段之前要充分考虑其生命周期及其潜在影响;另外也要注意初始化顺序可能带来的副作用。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值