1. 啥是异常
异常是编译时或者程序运行时出现的错误。异常如果不加以处理,一旦发生就会导致jvm退出,程序终止。
2. 异常的体系:Error and Exception
其中Error是系统级异常,代码无法控制,例如JVM退出。Exception则是程序可以处理的问题,运行时异常继承了RuntimeException
或者其子类,在编译阶段不会出现。编译时异常是指的Java编译成class文件时必须处理的异常,除了RuntimeException
以及其子类,其他的都是编译时异常。
3. 异常的处理
两种方法:捕catch
或抛throw
3.1 常见运行时异常
首先注意是直接继承自RuntimeException或者其子类,编译阶段是不会报错的。一般是业务没有考虑好,或者逻辑不严谨造成的异常,人话:你太菜了导致的异常!!!
运行时异常的示例:
- 数组索引越界异常 ArrayIndexOutOfBoundsException
比如试图访问一个超过最大下标的元素 - 空指针异常 NullPointerException
例如对一个空的字符串求使用length()方法 - 类型转换异常 ClassCastException
例如对一个Object类型的整数,类型强转为字符 - 数学操作异常 ArithmeticException
例如除0操作 - 数字转换异常 NumberFormatException
继承了 IllegalArgumentException
对于一个有一串的字符串“123aa”,要转为数字
3.2 常见编译时异常
编译时异常是这里很可能有问题,为了避免你技术太菜!在编译阶段就来提醒你了
编译时异常的示例:
- ParseException:在转换时包括了对象中不存在的Fields
- IO Exception
3.3 异常默认的处理机制
- 在出现异常代码处创建一个异常对象
- 异常对象会返回给调用者(Class or method)
- 然后调用者会把异常返回给main方法
- main方法再把异常给JVM
- JVM就在异常代码出现时终结程序,后续代码将不再执行
3.4 编译时异常的处理
三种方法:
- 默认的处理方式,直接抛而不处理
throws Exception
但是自己不处理异常,一旦出现异常,就会抛到虚拟机哪里去,程序就噶了 - 出现异常自己捕获并处理
发生异常的方法自己独立完成异常捕获处理,不会让程序噶掉。
一般直接一个try后面接一个catch块来捕获Exception
会有什么问题: - 先通过throws抛给调用者,然后调用者收到后统一处理
例如方法throws异常,在main函数里用try catch处理。
3.5 运行时异常处理
运行是异常在编译阶段不会出错,运行时才会出错,编译阶段可以不作处理,而是在最外层调用处进行集中地处理。
例如:原生java里的handler层,在handle方法里面处理Exceptions
3.6 throw and throws
throw 表示抛出一个异常类的对象,生成异常对象的过程。声明在方法体内。
throws 属于异常处理的一种方式,声明在方法的声明处。
4.合理的异常处理可以提高程序健壮性(Robustness)
例如:有个输入,要求是持续循环指导输入正确的数。此时如果输入了一堆字符,程序就会挂掉,但是定义了异常处理,那么仍然会正常运行
5.自定义异常
5.1 自定义编译时异常
定义一个异常类继承Exception,重写构造器,必须在方法签名处就用throws,在出现异常的地方通过throw new自定义的异常对象抛出。
日期转换异常其实就是这样自定义然后可以提示问题的,在实际开发中也许可以考虑将敏感业务写成自定义编译时异常,那么就会提前报错。
5.2 自定义运行时异常
定义一个异常类继承RuntimeException,重写构造器,在出现异常的地方抛出,然后在最外层捕获处理。对应是实际开发中不那么严重的情况。
例如下段代码所示的反序列化异常:
/**
* @author Cyan
* @version 1.0
*/
public class DeserializationException extends RuntimeException {
public DeserializationException(String message) {
super("Failed to deserialize: " + message);
}
}