递归
偶然想起了递归,印象里就是自己调用自己,还有 StackOverflowError
,为了加深印象,我们来详细说说递归。
概述
递归:指在当前方法内调用自己的这种现象。
递归的分类:
- 递归分为两种,直接递归和间接递归。
- 直接递归:方法自身调用自己。
- 间接递归: A 方法调用 B 方法,B 方法调用 C 方法,C 方法调用 A 方法。
注意事项:
- 递归一定要有条件限定,保证递归能够停止下来,次数不要太多,否则会发生栈内存溢出!
- 构造方法,禁止递归!
栈内存溢出原因分析
栈溢出原因就是,方法执行时创建的栈帧超过了栈的深度。最有可能的就是方法递归调用产生这种结果。
/*
*栈内存溢出原因分析
* */
public class Demo {
public static void main(String[] args) {
a();
}
private static void a() {
System.out.println("调用了 a 方法");
a();
}
/*
* a 方法会在 栈内存中一直调用 a 方法,就会导致栈内存中有无数个 a 方法
* 方法太多了,超出了栈内存的大小,就会导致,栈内存溢出
*
* 【注意:】
* 当一个方法执行过程中,调用其它方法的时候,被调用方法没有执行完毕,
* 当前方法会等待,调用方法执行完毕,才会继续执行
* */
递归求和
一般用 循环,不这么写
public static void main(String[] args) {
//计算1~num的和,使用递归完成
int num = 5;
// 调用求和的方法
int sum = getSum(num);
// 输出结果
System.out.println(sum);
}
public static int getSum(int num) {
/*
num为1时,方法返回1,
限定条件,num =1 停止。
*/
if(num == 1){
return 1;
}
/*
num不为1时,方法返回 num +(num-1)的累和
递归调用getSum方法
*/
return num + getSum(num-1);
}
递归阶乘
//计算n的阶乘,使用递归完成
public static void main(String[] args) {
int n = 3;
// 调用求阶乘的方法
int value = getValue(n);
// 输出结果
System.out.println("阶乘为:"+ value);
}
public static int getValue(int n) {
// 1的阶乘为1 限定条件 递归出口
if (n == 1) {
return 1;
}
/*
n不为1时,方法返回 n! = n*(n-1)!
递归调用getValue方法
*/
return n * getValue(n - 1);
}
递归遍历目录
分析:
- 遍历之前,无从知道到底有多少级目录,所以我们要使用递归实现。
- 遍历 e:/myfiles 目录 ,下面是它的结构
- myfiles 目录
- 1 号目录
- test1.txt
- test2.txt
- 2 号目录
- test1.txt
- test2.txt
- Test.txt
- 1 号目录
- myfiles 目录
递归遍历文件夹: 看不明白就 Debug
/*
* 案例1 :递归遍历文件夹
* */
public class ListDemo {
public static void main(String[] args) {
listDir(new File("e:\\myfiles"));
}
public static void listDir(File dir) {
// 得到 myfiles 下所有的文件和目录
File[] files = dir.listFiles();
// 输出一下要遍历目录的名称
System.out.println("我要遍历目录:" + dir.getAbsolutePath());
// 判断 是否为空 同时也是递归 跳出的条件
if (files != null && files.length > 0) {
// 不空,就遍历 files
for (File file : files) {
// 判断 是否是目录
if (file.isDirectory()) {
// 递归调用
listDir(file);
} else {
System.out.println(file.getAbsolutePath());
}
}
}
}
}
/*
结果:
* 我要遍历目录:e:\myfiles
我要遍历目录:e:\myfiles\1文件夹
e:\myfiles\1文件夹\test1 - 副本.txt
e:\myfiles\1文件夹\test1.txt
我要遍历目录:e:\myfiles\2文件夹
e:\myfiles\2文件夹\test2- 副本.txt
e:\myfiles\2文件夹\test2.txt
e:\myfiles\test.txt
*
* */
递归删除目录
递归删除文件夹:
/*
* 案例2 :递归删除文件夹
* */
public class ListDemo {
public static void main(String[] args) {
deleteDir(new File("e:\\myfiles"));
}
// 2 递归删除文件夹 delete 只能删除空目录
public static void deleteDir(File dir) {
// 得到 myfiles 下所有的文件和目录
File[] files = dir.listFiles();
// 输出一下要遍历目录的名称
System.out.println("我要删除:" + dir.getAbsolutePath());
// 判断 是否为空 同时也是递归 跳出的条件
if (files != null && files.length > 0) {
// 不空,就遍历 files
for (File file : files) {
// 判断 是否是目录
if (file.isDirectory()) {
// 是文件夹 ,就,递归,遍历把它的目录下的东西找出来删了
deleteDir(file);
} else {
// 删除文件
System.out.println(file.getAbsolutePath() + "删除文件:" + file.delete());
}
}
}
// 文件删完,把文件夹删了
System.out.println(dir.getAbsolutePath() + "删除目录:" + dir.delete());
}
}
/*
* 结果:
* 我要删除:e:\myfiles2
我要删除:e:\myfiles2\1号文件
e:\myfiles2\1号文件\test1 - 副本.txt删除文件:true
e:\myfiles2\1号文件\test1.txt删除文件:true
e:\myfiles2\1号文件删除目录:true
我要删除:e:\myfiles2\2号文件
e:\myfiles2\2号文件\test2 - 副本.txt删除文件:true
e:\myfiles2\2号文件\test2.txt删除文件:true
e:\myfiles2\2号文件删除目录:true
e:\myfiles2\Test.txt删除文件:true
e:\myfiles2删除目录:true
* */
本文来自博客园,作者:走马!,转载请注明原文链接:https://www.cnblogs.com/zou-ma/p/16156990.html
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 字符编码:从基础到乱码解决
· 提示词工程——AI应用必不可少的技术