1. 递归调用
所谓递归方法的调用,即在定义的方法体中运行方法本身,下面示例中run方法体又调用了run方法:
public class RecursiveMethodCall {public void run() {run();System.out.println("123");}public static void main(String[] args) {RecursiveMethodCall rmc = new RecursiveMethodCall();rmc.run();}}
2. 内存溢出
上面示例代码是可以正常编译的,但是运行就会报内存溢出(StackOverflowError)错误,其原因在于方法地递归调用是一个死循环,导致栈中不断地开辟新空间给run方法,这也就是我们常说的压栈。
细心的同学可能会问,当初我们在学习流程控制时,while (true)循环不也是死循环么,它为什么可以正常执行呢?
public class RecursiveMethodCall {public void run() {System.out.println("123");}public static void main(String[] args) {RecursiveMethodCall rmc = new RecursiveMethodCall();while (true) {rmc.run();}}}
显然,在主程序中所调用的rmc.run方法,其在栈中指向的地址是一样的,并不会因为循环而去开辟新的空间。但是,run方法中递归调用run方法,是会开辟新的空间给递归的run方法,所以内存会溢出。
3. 递归经典案例一:斐波那契数列
上面方法的递归调用其实是一个错误的示例,演示它的目的并不是告诉大家不要进行方法的递归调用。在某些情况下,使用方法的递归调用可以极大地减少代码量以及提高运行效率,接下来我们就介绍一个递归经典案例——斐波那契数列。
:::info
🧰 斐波那契数列
—————————————
1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610….
:::
public class Recursion {public long fibonacci(long n) {if (n == 1 || n == 2) {return 1;} else {return fibonacci(n - 1) + fibonacci(n - 2);}}public static void main(String[] args) {Recursion recursion = new Recursion();int n = 3;long number = recursion.fibonacci(n);System.out.println(n + ": " + number);}}
4. 递归经典案例二:阶层
public class Recursion {public long factorial(long n) {if (n == 1) {return 1;} else {return n * factorial(n - 1);}}public static void main(String[] args) {Recursion recursion = new Recursion();int n = 3;long number = recursion.factorial(n);System.out.println(n + ": " + number);}}
