递归
递归介绍
- 方法直接或者间接调用本身
- 注意:递归如果没有控制好终止,会出现递归死循环,导致栈内存溢出现象
- 一些算法题的实现, 都需要使用递归
public class RecursionDemo1 {/*递归介绍: 方法直接或者间接调用本身*/public static void main(String[] args) {methodA();}public static void methodA() {methodB();}public static void methodB() {methodC();}public static void methodC() {methodA();}
}
案例:计算5的阶乘如下
public static void main(String[] args) {int result = jc(5);System.out.println(result);}public static int jc(int num) {if (num == 1) {return 1;} else {return num * jc(num - 1);}
}
不死神兔 (斐波那契数列):
有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问第二十个月的兔子对数为多少?
public class RecursionDemo3 {public static void main(String[] args) {int result = get(20);System.out.println(result);}public static int get(int month) {if (month == 1 || month == 2) {return 1;} else {return get(month - 2) + get(month - 1);}}
}
猴子吃桃
猴子第一天摘下若干个桃子
当即吃了一半,还不过瘾,又多吃了一个
第二天早上又将剩下的桃子吃掉一半,又多吃了一个
以后每天早上都吃了前一天剩的一半零一个
到第10天早上想再吃时,见只剩下一个桃子了
求第一天共摘了多少桃子?
public static void main(String[] args) {System.out.println(monkey(1));
}public static int monkey(int num) {if (num == 10) {return 1;} else {// 公式 : (后一天的桃子数量 + 1) * 2;return (monkey(num + 1) + 1) * 2;}
}
异常
-
异常介绍
-
指的是程序在编译或执行过程中,出现的非正常的情况 (错误)
ArrayIndexOutOfBoundsException
ClassCastException
NullPointerException
…
注意 : 语法错误, 不是异常.
异常体系
Throwable :
Error
-
严重级别问题
常见的 : 栈内存溢出 (StackOverflowError) 堆内存溢出 (OutOfMemoryError)
Exception:
-
RuntimeException 及其子类:运行时异常
-
除RuntimeException 之外所有的异常:编译时异常
编译时异常
编译阶段就出现的错误
主要起到提醒作用
运行时异常
-
数组索引越界异常: ArrayIndexOutOfBoundsException
-
空指针异常 : NullPointerException
-
数学操作异常:ArithmeticException
-
类型转换异常:ClassCastException
-
数字转换异常: NumberFormatException
-
小结:编译阶段没有错误, 运行时 [可能] 会出现的错误
这种错误通常都是程序员代码不严谨所造成的
异常的处理方式
异常的默认处理流程
①虚拟机会在出现异常的代码那里自动的创建一个异常对象:ArithmeticException
②异常会从方法中出现的点这里抛出给调用者,调用者最终抛出给JVM虚拟机
③虚拟机接收到异常对象后,先在控制台直接输出异常信息数据
④终止 Java 程序的运行
⑤后续代码没有机会执行了,因为程序已经噶了
异常处理方式 try…catch…
-
能够将抛出的异常对象捕获,然后执行异常的处理方案
-
好处:程序可以继续往下执行
格式:
try {可能会出现异常的代码} catch(异常类型1 变量) {处理异常的方案*} catch(异常类型2 变量) {处理异常的方案}
注意: 如果使用多个catch, 最大的异常需要放在最后
异常处理方式 throws 抛出
问题: 正在面临的异常, 是否需要暴露出来
-
不需要暴露 : try…catch捕获
-
需要暴露 : 抛出异常
-
throw 和 throws 的区别
throw : 用在方法中, 后面跟的是异常对象, 其作用是抛出异常对象
throws : 用在方法名后面, 起到声明作用
声明此方法中存在异常, 调用者需要进行处理
- 细节 :
抛出的异常对象如果是编译时异常, 必须使用 throws 声明
如果是运行时异常, 则不需要写 throws
自定义异常
自定义异常的必要
-
Java无法为这个世界上全部的问题提供异常类。
-
如果企业想通过异常的方式来管理自己的某个业务问题,就需要自定义异常类了。
自定义异常的分类
1、自定义编译时异常
-
定义一个异常类继承Exception.
-
重写构造器
2、自定义运行时异常
-
定义一个异常类继承RuntimeException.
-
重写构造器。
异常的细节
- Throwable的常用方法 :
方法名 | 说明 |
---|---|
public String getMessage() | 获取异常的错误原因 |
public void printStackTrace() | 展示完整的异常错误信息 |
- 子类重写父类方法时,不能抛出父类没有的异常, 或者比父类更大的异常