学习目录:
- 方法的细节小科普、
- 知道什么是递归
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 的公共类 |
开发者在使用递归时需要非常小心,因为很容易编写出一个无法终止的函数,或者一个消耗过多内存和处理器资源的函数。
然而,当递归写得正确时,它可以成为一种非常高效且具有数学优雅性的编程方法。