今天是我自学Java的第38天。
感谢你的观看,谢谢你。
话不多说,开始今天的学习:
递归:不要看这个名字好像挺高大上的样子,其实理解起来还是蛮容易的。
在学习递归之前,我们先学习下目录的遍历,递归的主要使用途径就需要它。
一、目录的遍历
目录,自然也就是指我们常说的文件夹了,一个文件夹里面是可以有很多个子文件夹和子文件的。
如果遍历目录?有两种方法:
1.目录的遍历:list方法
①创建一个文件对象
因为是目录的遍历,所以在路径中填写目录的路径。②list方法
list,列表的意思,一个文件夹里面有几个文件夹或者文件,这就是一个获取文件夹里的列表的方法。
返回一个String数组,表示该File目录中的所有子文件或目录。
③遍历目录
使用增强for循环,控制台会输出一个目录列表。
2.目录的遍历:listFiles方法
①创建一个文件对象
②listFiles方法
返回一个File数组,表示该File目录中的所有的子文件或目录。
③遍历目录
使用增强for循环,控制台会输出一个目录列表(带完整路径的)。
其中可以使用file的getName方法获取文件名列表。
目录的遍历特点:
只能遍历目录,不能遍历文件。listFiles方法更加地常用,因为file有各种各样的方法,我们可以根据需求遍历出不同的格式。因为File根据构造方法的路径,既能表示成文件又能表示成目录,如果填写文件路径会返回null,遍历的话就会出现空指针异常。二、递归(recursion)
说到递归,先提一个数学里的概念:阶乘。
什么叫阶乘?
5的阶乘:5!=5×4×3×2×1;
4的阶乘:4!=4×3×2×1。
这就是阶乘。
现有一个需求:求一个数的阶乘?
1.for循环解决该需求
看到这个需求我的第一个反应就是for循环,事实上确实可以用循环语句解决:
①定义一个计算阶乘的方法:getResult()。
②在getResult中,定义一个变量作为阶乘的结果。
③for循环计算阶乘,并返回结果。
注意:0!=1,而不是想当然的以为等于0;
至于为什么为1,这是一个数学问题。
本质上n!=(n+1)!÷(n+1);
所以:0!=1!÷1=1。
那除了for循环还有没有其他方法呢?
答案是有的,也就是递归。
2.递归解决该需求
①定义一个计算阶乘的方法。
②i==0,0的阶乘等于1,直接返回1。
③i0时,找出其中的计算规律。
如果getResult(i-1)就是(i-1)!
那么getResult(i)=i*getResult(i-1)。
看到没有,什么叫递归?
递归就是指在方法里面调用自己的方法这种现象。
就像我们在数学中的找规律一样,先把规律找出来,再创建方法。
④如果是负数,因为负数是没有阶乘的,直接返回-1,或者报错。
递归注意点:
递归必须要有结束条件,不然的话就是死循环了。stackOverflowError:栈溢出,如下图:
因为递归指的是方法里面调用自己的方法,如果一次性地调用次数过多会出现栈溢出的情况,并且这是一种错误,无法从代码角度修改。
其中上述两种方法中:
for循环的方法要更加地实用简洁,使用递归的话效率会很低,一般使用的很少。
那为何还要学递归?
因为它在文件操作中会使用到它,并且既然是学习Java,也有必要理解下递归的概念。
三、递归删除多级目录
根据我们昨天学的File类中的方法。
删除方法delete只能用来删除文件和空文件夹,它是没法直接删除非空文件夹的。
那你可能要问了,那计算机里面可以直接删除一个非空文件夹的呀,它是怎么做到的?
其实删除非空文件夹的操作本质上就是:先将文件夹里面的所有文件都删除,等自己成一个空文件夹了,再删除自己。
这个需求如何实现?
就需要使用到递归。
①创建file对象,定义一个deleteFile的方法
其中路径为多级文件夹,所以不能用delete方法直接删除,deleteFile方法可以用来删除一个文件夹。
②delete方法中如果file对象是文件
是文件的话,可以使用delete方法直接删除。
③如果是文件夹,我们需要遍历
将文件夹遍历,使用我们一开始学到的listFiles方法。
遍历之后,文件夹里面也是有可能既包含文件夹又包含文件的,还是要判断,又回到了一开始的需求。
④递归
在方法里直接调用自己的方法就好了。
⑤删除空文件夹
因为文件夹里的文件夹和文件都没有了,就是一个空文件夹了,所以可以直接删除。
总之,使用递归把握两点:
如何结束递归?如何继续递归?上述例子中:
如何结束递归?
当file对象是一个文件时(使用isFile方法),直接就可以删除文件了,结束递归。
如何继续递归?
我们是要删除一个文件夹,使用了一个deleteFile方法。
因为一个文件夹里面是可能既有文件夹又有文件的。
如果是文件,直接删除。如果是文件夹,继续使用deleteFile方法说白了,递归就是寻找逻辑点相同的地方,再自己调用自己的方法就好了。
总结