学习目录:
- 方法的细节小科普、
- 知道什么是递归
Java 范围
在 Java 中,变量只能在它们被创建的区域内访问。这被称为作用域
块级作用域
代码块指的是花括号 {}
之间的所有代码。
在代码块内声明的变量只能在花括号之间的代码中访问,并且只能在声明该变量的代码行之后访问
示例:
1 | public class Main { |
解释:
在这个示例中,变量 x
在代码块 {}
内部声明,并且只能在该代码块内访问。代码块外部无法访问 x
注意:
代码块可以单独存在,或者作为 if
、while
、for
等语句的一部分。当变量在这些语句的内部声明时,这些变量也可以在对应的代码块内使用。代码块外部也一样无法访问 x
递归
递归是让一个函数调用自身的技术。这种技术提供了一种将复杂问题拆解成更简单问题的方式,从而更容易解决。
递归示例
将两个数字相加是一个简单的操作,但将一系列数字相加则更为复杂。在以下示例中,递归被用来通过将其分解成简单的两个数字相加的任务,来实现对一系列数字的求和:
1 | public class Main { // 定义一个公共类 Main |
在递归调用中,return k + sum(k - 1);
这一行中,k
的值是在每一次递归时由调用 sum(k)
时传入的参数决定的。
1. 递归过程中的 k
值
- 初始调用是
sum(10)
,所以在第一次递归时,k
的值是 10。 - 然后,
sum(10)
调用sum(9)
,此时k
的值变成了 9。 - 接着,
sum(9)
调用sum(8)
,k
的值变成了 8。 - 这个过程会一直递减,直到
k
变为 0,即sum(0)
。
2. 递归调用展开:
假设我们调用 sum(10)
,下面是递归的展开过程,每次 sum(k)
中的 k
都是前一次调用传入的值:
sum(10)
计算为10 + sum(9)
,此时k = 10
。sum(9)
计算为9 + sum(8)
,此时k = 9
。sum(8)
计算为8 + sum(7)
,此时k = 8
。sum(7)
计算为7 + sum(6)
,此时k = 7
。sum(6)
计算为6 + sum(5)
,此时k = 6
。sum(5)
计算为5 + sum(4)
,此时k = 5
。sum(4)
计算为4 + sum(3)
,此时k = 4
。sum(3)
计算为3 + sum(2)
,此时k = 3
。sum(2)
计算为2 + sum(1)
,此时k = 2
。sum(1)
计算为1 + sum(0)
,此时k = 1
。sum(0)
返回0
,此时k = 0
。
3. 递归的回溯过程:
当 k
达到 0 时,递归开始回溯,每一次回溯时 k
的值就会与之前保存的值相加:
sum(1)
返回1 + 0 = 1
。sum(2)
返回2 + 1 = 3
。sum(3)
返回3 + 3 = 6
。sum(4)
返回4 + 6 = 10
。sum(5)
返回5 + 10 = 15
。sum(6)
返回6 + 15 = 21
。sum(7)
返回7 + 21 = 28
。sum(8)
返回8 + 28 = 36
。sum(9)
返回9 + 36 = 45
。sum(10)
返回10 + 45 = 55
。
最终结果是 sum(10)
返回 55
。
在 return k + sum(k - 1);
中,k
的值是每一次递归调用时传入的参数值。在初始调用时,k
是 10,每次递归调用时 k
会递减,直到达到 0 为止。
4. 终止条件
就像循环可能遇到无限循环的问题一样,递归函数也可能遇到无限递归的问题。无限递归是指函数不断地调用自己,永远无法停止。每个递归函数都应该有一个终止条件,即函数停止调用自己的条件。在前面的例子中,终止条件是当参数 k
变为 0 时。
通过查看不同的示例,能够更好地理解这个概念。在这个例子中,函数的作用是计算从起始值到结束值之间的所有数字之和。这个递归函数的终止条件是当 end
不大于 start
时:
示例
使用递归计算从 5 到 10 之间的所有数字的和。
1 | public class Main { // 定义一个名为 Main 的公共类 |
开发者在使用递归时需要非常小心,因为很容易编写出一个无法终止的函数,或者一个消耗过多内存和处理器资源的函数。
然而,当递归写得正确时,它可以成为一种非常高效且具有数学优雅性的编程方法。