什么是递归呢,我不想将理论上的东西放到这里描述,只是通过自己的一些理解,去描述它,并做了一些小小的实验。如果有什么错误的地方,博主欢迎大家留言指正。
首先看看下边的这几行代码
package skill;
public class skillClassTs {
//自身调用
public void self(){
self();
}
//方法间的调用
public void fun(){
System.out.println("fun method has called");
fun2();
}
public void fun2(){
fun();
}
public static void main(String[] args) {
skillClassTs sct = new skillClassTs();
sct.fun();
}
}
连成了一个环,不断反复调用直到抛出一个 StackOverflowError异常 适当添加一个条件便是递归。这里有两种方式的递归,1:自身,2:方法间形成递归。
递归就是可以在某个阶段跳出一个死循环,一般是方法间的自身调用或者是多个方法间的调用,这多个方法要求能够连成环的,先构成一个死循环,然后再添加条件能在执行满足条件后跳出。
刚接触的时候对递归一层层下来,又一层一层上去很惊奇,其实也没什么大不了,不过是函数在调用另一个函数的时候会现场记录及一些数据的保存罢了,当被调函数结束后,就会返回原先的位置,继续执行。
好了,下面我们要进入探索阶段了:
package skill;
/**
* 我想实现的功能是:
* struts2的拦截器实现的思想
* 事情1 事情2 事情3 处理 事情1release 事情2 release 事情3 release
*
* @author 追本溯源
*
*/
public class skillClassTs {
private int index = 0;
private String[] things = new String[]{"事情1","事情2","事情3"};
/** 首先用我熟悉的纵向递归实现**/
public void fun(String receiver){
if(receiver!=null){
try{
//该事件的一些处理
dealFunBegin(receiver);
fun(things[index++]);
}catch(ArrayIndexOutOfBoundsException e){
fun(null);
}
invokeThings();
dealFunEnd(receiver);
}
}
//ivokeThings处理之前的的一系列处理
public void dealFunBegin(String receiver){
System.out.println(receiver+"事件开始处理");
}
public void invokeThings(){
System.out.println("中间主要的操作");
}
//invokeThings处理之后的一系列处理
public void dealFunEnd(String receiver){
System.out.println(receiver+"事情处理完毕");
}
public static void main(String[] args) {
skillClassTs sct = new skillClassTs();
sct.fun("开始事情处理");
}
}
结果
开始事情处理事件开始处理
事情1事件开始处理
事情2事件开始处理
事情3事件开始处理
中间主要的操作
事情3事情处理完毕
中间主要的操作
事情2事情处理完毕
中间主要的操作
事情1事情处理完毕
中间主要的操作
开始事情处理事情处理完毕
发现所谓的纵向递归不能实现上面的功能
无奈,加个标记
package skill;
/**
* 我想实现的功能是:
* struts2的拦截器实现的思想
* 事情1 事情2 事情3 处理 事情1release 事情2 release 事情3 release
*
* @author 追本溯源
*
*/
public class skillClassTs {
private int index = 0;
boolean falg = false;
private String[] things = new String[]{"事情1","事情2","事情3"};
/** 首先用我熟悉的递归实现**/
public void fun(String receiver){
if(receiver!=null){
try{
//该事件的一些处理
dealFunBegin(receiver);
//这里参数用数组取出来比较省力
//如果比较复杂那么在上边写个函数封装
//反正结果就是用取数据一句话来概括
fun(things[index++]);
}catch(ArrayIndexOutOfBoundsException e){
fun(null);
}
if(!falg){
invokeThings();
falg = true;
}
dealFunEnd(receiver);
}
}
//ivokeThings处理之前的的一系列处理
public void dealFunBegin(String receiver){
System.out.println(receiver+"事件开始处理");
}
public void invokeThings(){
System.out.println("中间主要的操作");
}
//invokeThings处理之后的一系列处理
public void dealFunEnd(String receiver){
System.out.println(receiver+"事情处理完毕");
}
public static void main(String[] args) {
skillClassTs sct = new skillClassTs();
sct.fun("开始事情处理");
}
}
额,这里的能够保证delFunBegin 和 dealFunEnd都是在同一层的,至于什么是同一层的请看下边的解释
模仿struts2拦截器的实现:struts2采用的递归是方法间的递归。
package skill;
/**
* 模仿struts2拦截器部分的递归
* 进行适当的更改
* @author 追本溯源
*
*/
public class skillRecursionTs {
private String[] things = new String[]{"事情1","事情2","事情3"};
private int index = 0;
/**事情1 事情2 事情3 主要操作 事情1release 事情2release 事情3release **/
private int cursor = 0;
public void invoke(){
//这里的if else用的好,比我前面用falg强很多。
if(index<things.length){
interceptor(things[index++]);
//System.out.println("额,开始返回了"+cursor++);
}else{
System.out.println("主要操作执行");
}
}
public void interceptor(String thing){
//有没有发现这两个输出中的thing在无轮什么时候都是同一个的。
//这样确保了它们间的匹配,不会出现自身递归的蛋疼
System.out.println(thing+"开始执行了");
invoke();
//System.out.println("额,这里也开始返回了--");
System.out.println(thing+"执行结束");
}
public static void main(String[] args) {
skillRecursionTs srt = new skillRecursionTs();
srt.invoke();
}
}
模仿上边递归,改进之前的代码:
package skill;
/**
* 针对skillRecusionTs适当修改skillClassTs
* @author 追本溯源
*
*/
public class skillVariatyTs {
private String[] str = new String[]{"事情1","事情2","事情3"};
private int index = 0;
/**
* 这里为什么出现这样的错误呢?
* 因为事情1 事情1释放 在下面的逻辑中不能保证是同一层。
* 如果没有主要操作处理这个碍眼的家伙倒是都在同一层次上,即一层层返回时,处理结束的目标资源总能和上边的开始处理资源对应(同一个)
* 但是如果有主要操作进行处理,那么,在这一层上只执行了endOperator(),悲剧的是还是数组越界。
*/
public void fun(){
if(index < str.length){
System.out.println(str[index++]+"进行处理了");
fun();
endOperator(); //放在这里保证成对出现
}else{
//index = str.length-1;
System.out.println("主要操作进行处理了");
}
//数据越界,不得不用标记解决?
//if(!falg){
//falg = true;
//上述分析,保证同一层,那么就不能放到这里
//endOperator();
//}
}
public void endOperator(){
System.out.println(str[--index]+"处理结束了");
}
public static void main(String[] args) {
skillVariatyTs svt = new skillVariatyTs();
svt.fun();
}
}
同一层 即:递归一层层下去,最后会一层层上来,这里的每一层他们的数据时不同的。这里要保证事情的处理和事情的释放在每一层上都要对应。像上边注释的endOperator 如果按这种逻辑写,那么在事情处理完,进行主要操作的时候,就不能保证有一个事情处理的函数与之对应。况且主要操作根本就不需要endPerator
好了,上边的自身的递归方式,也能实现如struts2的拦截器功能。