14、异常处理
异常发生的原因
- 概念:程序在运行过程中出现的特殊情况。
- 用户输入了非法数据。
- 要打开的文件不存在。
- 网络通信时连接中断,或者JVM内存溢出
异常处理的必要性
- 任何程序都可能存在大量的未知问题、错误;如果不对这 些问题进行正确处理,则可能导致程序的中断,造成不必要的损失。
相当于遇到 return语句,导致程序因异常而终止。
异常的产生
- 自动抛出异常:当程序在运行时遇到不符合规范的代码或结果时,会产生异常。
- 手动抛出异常:语法:throw new 异常类型(“实际参数”);
异常的传递
- 异常的传递:按照方法的调用链反向传递,如始终没有处理异常,最终会由 JVM进行默认异常处理(打印堆栈跟踪信息)并中断程序。
Throwable
-
Error
- JVM、硬件、执行逻辑错误,不能手动处理。
-
Exception
-
程序在运行和配置中产生的问题,可处理。
-
所有的异常类是从 java.lang.Exception 类继承的子类
Exception 类是 Throwable 类的子类 -
RuntimeException
-
运行时异常,又称不受检查异常,可处理,可不处理。无需声明异常。
系统运行时产生的异常,编译时不会告诉你有这个异常,只有运行时才会暴露出来 -
常见运行时异常
- NullPointerException 空指针异常
- ArrayIndexOutOfBoundsException 数组越界异常
- ClassCastException 类型转换异常
- NumberFormatException 数字格式化异常
- ArithmeticException 算术异常
-
-
CheckedException
-
检查时异常,必须处理。
- 1:throw到上层,
- 2,try-catch处理。
-
throws 声明异常,修饰在方法参数列表后端。
-
-
-
Throwable
-
public String getMessage()
- 返回关于发生的异常的详细信息
-
public void printStackTrace()
- 打印toString()结果和栈层次到System.err,即错误输出流
-
异常处理
-
try/catch
- try{
// 程序代码
}catch(异常类型1 异常的变量名1){
// 程序代码
}catch(异常类型2 异常的变量名2){
// 程序代码
}catch(异常类型2 异常的变量名2){
// 程序代码
}
- try{
-
throws/throw
-
如果一个方法没有捕获一个检查性异常,那么该方法必须使用 throws 关键字来声明
底层代码向上声明或者抛出异常,最上层一定要处理异常,否则程 序中断。 -
throws 关键字放在方法签名的尾部
-
也可以使用 throw 关键字抛出一个异常
- 语法: throw 异常对象
-
一个方法可以声明抛出多个异常,多个异常之间用逗号隔开
-
-
finally
- finally 关键字用来创建在 try 代码块后面执行的代码块。
- 无论是否发生异常,finally 代码块中的代码总会被执行。
- 在 finally 代码块中,可以运行清理类型等收尾善后性质的语句。
- finally 代码块出现在 catch 代码块最后
- try{
// 程序代码
}catch(异常类型1 异常的变量名1){
// 程序代码
}catch(异常类型2 异常的变量名2){
// 程序代码
}finally{
// 程序代码
}
自定义异常
-
概念:需继承Exception或Exception的子类,代表特定问题。
-
经验:异常类型名称望文生义,可在发生特定问题时抛出对应的异常。
-
常用构造方法:
- 无参数构造方法
- String message参数的构造方法
注意事项:
- 多重catch,遵循从子( 小 )到父( 大 )的顺序,父类异常在最后。
- finally块是否发生异常都执行
- finally块不执行的唯一情况,退出java虚拟机
- 子类异常在前,父类异常在后
发生异常时按顺序逐个匹配
只执行第一个与异常类型匹配的catch语句
finally根据需要可写或不写 - try…finally…不能捕获异常,仅仅用来当发生异常时,用来释放资源
一般用在底层代码,只释放资源不做异常处理,把异常向上抛出。