java复习笔记——异常
- 异常类型
- 抛出异常
- 捕获异常
- 自定义异常块
异常类型
Checked Exceptions
检查性异常:一般指用户错误或问题引起的异常,例如输入错误,打开不存在的文件等。必须进行异常处理,try catch或者外抛,否则编译错误。
Runtime Exceptions
运行时异常:可能被程序员避免的异常,编译器不会检查到,一般因为代码设计上的原因出现,常见的如 除以0、空指针、下标越界等。
Error
错误:错误是脱离程序员控制的问题。例如内存用光,线程池错误等等,编译时检查不到。
Java标准库定义的常用异常与错误包括:
抛出异常
抛出异常:
抛出异常指的是将异常抛给调用的方法处理。
例如方法A调用了B,B调用了C。
C中抛出了一个异常,B可以选择继续处理或是继续抛出。如果B处理了,A就不会接收到这个异常,B抛出的话,A就需要处理或继续抛出这个异常。
throw与throws
区别点 | throw | throws |
---|---|---|
位置 | 方法体内 | 方法声明上 |
数量 | 一个异常对象名 | 多个用逗号隔开 |
处理方 | 由方法体处理或抛出throws | 方法调用者处理 |
是否发生异常 | 一定抛出了某种异常 | 可能会发生此异常 |
public void C () throws Exception{
//throws在方法后边声明异常,此方法不对异常做处理,由调用者处理
}
//-----------------------------------------------------------
public void B() throws Exception {
//抛出
throw new Exception();
}
public void B2(){
//方法体处理
try {
throw new Exception();
} catch (Exception e) {
e.printStackTrace();
}
}
捕获异常
try…catch
所有的异常也都可以由其父类catch,不过一般不建议这样做,异常信息应该越详细越好。
public void A(){
try {
B();
//1、捕获可能会出现异常的代码块
//2、此处B中由throw一定抛出了异常
} catch (Exception e) {
e.printStackTrace();
//异常的处理
}
B2();
}
在jdk1.7之后,有了try()…catch…,在try()括号中申请的资源会自动被关闭,不用再手动关闭,前提是这个资源实现了AutoCloseable接口的类,括号中多个资源用分号隔开。
try(FileInputStream fis = new FileInputStream(file);
InputStreamReader read = new InputStreamReader(fileInputStream);){
}catch(Exception e){
}finally{
//正常情况下我们需要在这写代码关闭try中的资源,用try()则会自动关闭括号中的资源。
}
多异常捕获
- 可以使用多个catch语句,每个catch分别捕获对应的Exception及其子类。
- JVM在捕获到异常后,会从上到下匹配catch语句,匹配到某个catch后,执行catch代码块,然后不再继续匹配。
- catch的顺序很重要,一般是子类在上,如果父类在上,子类就永远捕获不到。
- 多个catch只有一个会被执行。
由两种多异常捕获方法:
//使用多个catch捕获
try{
// 程序代码
}catch(异常类型1 异常的变量名1){
// 程序代码
}catch(异常类型2 异常的变量名2){
// 程序代码
}catch(异常类型3 异常的变量名3){
// 程序代码
}
//或是如下多个异常放一个catch捕获
try{
// 程序代码
}catch(异常类型1 |异常类型2 异常的变量名){
// 之后再进行判断
if (异常的变量名 instanceof 异常类型1)
//程序代码
if (异常的变量名 instanceof 异常类型2)
//程序代码
}
finally
- finally语句不是必须的,可写可不写;
- finally总是最后执行,且必定会执行。
public static int test(){
try{
int k[] = new int[1];
int a = k[2];
return 1;
}catch(ArrayIndexOutOfBoundsException e){
return 2;
}finally{
//如果finally中有ruturn,则闭定会从finally中返回
//如果finally中没有ruturn,在try或catch中有return,无论是否发生异常,都会执行finally中的代码后再执行return。
System.out.println("finally");
return 3;
}
}
自定义异常
在 Java 中你可以自定义异常。编写自己的异常类时需要记住下面的几点。
- 所有异常都必须是 Throwable 的子类。
- 如果希望写一个检查性异常类,则需要继承 Exception 类。
- 如果你想写一个运行时异常类,那么需要继承 RuntimeException 类。
在一个大型项目中,可以自定义新的异常类型,但是,保持一个合理的异常继承体系是非常重要的。
一个常见的做法是自定义一个 BaseException 作为根异常,然后,派生出各种业务类型的异常。
BaseException需要从一个适合的Exception派生,通常建议从RuntimeException派生:
public class BaseException extends RuntimeException {
}
其他业务类型的异常就可以从BaseException派生:
public class UserNotFoundException extends BaseException {
}
public class LoginFailedException extends BaseException {
}
...
自定义的BaseException应该提供多个构造方法:
public class BaseException extends RuntimeException {
public BaseException() {
super();
}
public BaseException(String message, Throwable cause) {
super(message, cause);
}
public BaseException(String message) {
super(message);
}
public BaseException(Throwable cause) {
super(cause);
}
}
参考java包中所继承的RuntimeException。这样,抛出异常的时候,就可以选择合适的构造方法。通过IDE可以根据父类快速生成子类的构造方法。
参考:
https://www.liaoxuefeng.com/wiki/1252599548343744/1255943543190176
https://www.runoob.com/java/java-exceptions.html