Java递归调用中用n--替代n-1为何出现栈溢出错误?
问题根因
n--和n-1的执行逻辑存在本质差异,两者在这个传参场景下的效果完全不同,这是触发栈溢出的核心原因。
核心规则差异
n-1是普通算术表达式:仅计算n减1的结果,不会修改当前作用域内n变量本身的值,表达式直接返回减1后的计算结果。n--是后缀自减运算符:属于带副作用的运算符,执行逻辑是先返回n当前的原始值,再把当前作用域的n变量值减1,表达式返回的是自减前的旧值。
错误代码的执行逻辑
你在递归调用时写recursivePrint(n--),实际执行顺序是:
- 先读取当前n的原始值,作为方法调用的实参
- 将当前方法栈帧内的局部变量n减1
- 携带第一步拿到的原始n值进入下一层递归
实际跑起来的流程是这样的:第一层调用传入n=5,判断5<1不成立,执行n--,取出原始值5作为下一层的入参,本层n被修改为4;第二层拿到的入参还是5,判断5<1不成立,再次执行n--,又取出原始值5传给下一层,本层n被修改为4。后续每一层递归拿到的入参永远是5,永远触发不了n<1的递归终止条件,方法会无限嵌套调用,直到栈内存被占满,最终抛出StackOverflowError。
别觉得换成前缀自减
--n就能解决问题,--n确实是先把n减1再传值,但它同样会修改当前栈帧里的n,等后面执行System.out.print(n)的时候,拿到的是已经被改掉的n值,打印出来的顺序全错。这里递归传参只需要一个n减1的计算结果,根本没必要改动当前方法里的n变量,所以不管是前缀还是后缀的自减,都不适合用在这个位置。
正确代码的执行逻辑
当你使用recursivePrint(n-1)传参时:
- 表达式不会修改当前方法栈帧内的n值,直接计算出n-1的结果作为实参传入下一层
- 递归入参从5→4→3→2→1→0逐层递减,当入参为0时触发终止条件开始回溯
- 每层回溯时打印的都是当前栈帧内未被修改的原始n值,最终正常输出
1 2 3 4 5。
内容的提问来源于stack exchange,提问作者Achyut Dalai
相关产品推荐
相关产品推荐

