Java异常处理
2021-04-20 11:38:02
## 什么是异常处理
异常本质上是程序上的错误,包括程序逻辑错误和系统错误。比如使用空的引用、数组下标越界、内存溢出错误等,这些都是意外的情况。因此,如何对运行期间出现的错误进行处理和补救呢?Java提供了异常机制来进行处理,通过异常机制来处理程序运行期间出现的错误。
## 异常体系架构
在Java中异常被当做对象来处理,根类是java.lang.Throwable类,所有异常类都继承于它,异常类分为两大类:Error和Exception。
- Error错误:错误不是异常,而是脱离程序员控制的问题,错误代码通常被忽略,例如:当栈溢出的时候,一个错误就发生了,他们在编译的时候也是检查不到的。
- Exception异常
- 运行时异常(间接或直接继承RuntimeException):这些异常通常时程序的逻辑出现了错误,当出现此类异常时,应该分析程序的逻辑是否正确。
- 检查时异常(不间接或不直接继承RuntimeException):这类异常,是程序必须进行处理的异常,否则不能被编译,即需要显示处理。
>总结 Error 与Exception的区别:异常Exception能被程序本身处理,错误Error是无法处理的
#### java异常体系图
![javaException.jpg](https://static.daimaku.net/post/202104/20/efc54dd91036c3c6db5510c1b02db719.jpg)
## Java中如何处理异常
java中处理异常分为两种,一种是`抛出异常`,另一种是`捕获异常`,其中有五个关键字,需要大家去了解一下,`try`、`catch`、`finally`、`throw`、`throws`
### 捕获异常
当你发现有段代码有不可控的因素在里面的时候,就可以运用到捕获异常,如下代码
```java
public class App {
public static void main(String[] args) {
int a = 1;
int b = 0;
// 有异常的代码
try{
System.out.println(a/b); // 1/0会报错
}catch(ArithmeticException e ){ // catch 中写上 异常的类型
// 捕获异常后 处理的操作 比如打印一句话
System.out.println("分母不能为0");
}finally{ // 无论是否存在异常,代码都会执行到finally,可以不写
System.out.println("方法执行完毕~");
}
}
}
```
注意catch中的异常类型 ,首先试试以下代码
```java
public class App {
public static void main(String[] args) {
// 有异常的代码
try {
// 会出现递归的错误
new App().a();
} catch (ArithmeticException e) { // catch 中写上 异常的类型
// 捕获异常后 处理的操作 比如打印一句话
System.out.println("出现异常!");
} finally { // 无论是否存在异常,代码都会执行到finally,可以不写
System.out.println("方法执行完毕~");
}
}
public void a() {
b(); // a中调用b方法
}
public void b() {
a(); // b中调用a方法
}
}
```
你会发现,catch中并没有捕获异常,因为这个错误类型,它是`ERROR`不属于这个异常类型之中,我们可以尝试换成异常的根类`Throwable`试试看能不能捕获到异常信息把?
```java
public class App {
public static void main(String[] args) {
// 有异常的代码
try {
// 会出现递归的错误
new App().a();
} catch (Throwable e) { // catch 中写上 异常的类型
// 捕获异常后 处理的操作 比如打印一句话
System.out.println("出现异常!");
} finally { // 无论是否存在异常,代码都会执行到finally,可以不写
System.out.println("方法执行完毕~");
}
}
public void a() {
b(); // a中调用b方法
}
public void b() {
a(); // b中调用a方法
}
}
```
运行结果成功捕获异常
java 中还提供了捕获多个异常
```java
public class App {
public static void main(String[] args) {
int a = 1;
int b = 0;
// 有异常的代码
try {
System.out.println(a / b); // 1/0会报错
} catch (Error e) {
System.out.println("Error");
} catch (Exception e) {
System.out.println("Exception");
} catch (Throwable e) { // 父类放到下面子类下面,包含关系,从小到大
System.out.println("Throwable");
} finally {
System.out.println("方法执行完毕~");
}
}
}
```
### 抛出异常
抛出异常一般是写在方法上,如下代码
```java
public class App {
public static void main(String[] args) {
int a = 1;
int b = 0;
// 调用test方法
new App().test(1, 0);
}
public void test(int a, int b) {
if (b == 0) {
throw new ArithmeticException(); // 主动抛出异常,一般在方法中使用
}
}
}
```
运行代码,你会发现代码就会在执行到`throw new ArithmeticException` 那一刻中断
如果我们想让代码抛出异常之后继续执行,该如何操作呢?
```java
public class App {
// 在方法后面加上 throws + 异常对象的类型 (ArithmeticException、Excetion 、Throwable)
public void test(int a, int b) throws ArithmeticException {
if (b == 0) {
throw new ArithmeticException(); // 主动抛出异常,一般在方法中使用
}
}
public static void main(String[] args) {
// 在调用方法的地方捕获异常
try {
new App().test(1, 0);
} catch (ArithmeticException e) {
// 可以写一些处理异常的代码
System.out.println("出现异常错误~");
}
// 代码会继续往下执行
System.out.println("继续执行代码");
}
}
```
### 自定义异常
用户可以自定义异常类,只需要继承Exception类即可,一般情况下用的不多。
新建一个异常类`XueBaException`
```java
public class XueBaException extends Exception {
private int detail ; //声明一个变量
// 构造器
public XueBaException(int a){
this.detail = a ;
}
@Override
public String toString() {
return "XueBaException{" +
"detail=" + detail +
'}';
}
}
```
写一个测试方法调用`XueBaException`异常类
```java
public class App {
// 在方法后面加上 throws + 异常对象的类型 (ArithmeticException、Excetion 、Throwable)
public void test(int a) throws XueBaException {
if (a > 10) {
throw new XueBaException(a); // 主动抛出异常,一般在方法中使用
}
}
public static void main(String[] args) {
// 捕获异常
try {
new App().test(11);
} catch (XueBaException e) {
System.out.println(e);
}
}
}
```