Java笔记:异常处理

时间:2022-05-08 19:39:45

一、基础知识

异常是用来描述代码中发生的异常情况的对象。当出现引起异常的情况时,就会抛出异常对象。方法可以选择自己处理异常或继续抛出异常。异常可以由Java运行时系统生成,也可以手动生成。由Java抛出的异常与违反语言规则或执行环境约束的基础性错误有关,手动生成的异常通常用于向方法的调用者报告某些错误条件。

 

二、异常类型

所有的异常类型都是Throwable的子类。Throwable位于异常类层次的顶部,紧随的两个分支是Exception和Error。Exception可用于捕获,也可用于自定义异常。Error则定义了在常规环境下不能由程序捕获的异常,通常是为了响应灾难性失败。

 

三、捕获异常

Java笔记:异常处理Java笔记:异常处理
class Solution {
public static void main(String[] args) {
String s
= "ABC";
try {
int a = Integer.parseInt(s);
System.out.println(a);
}
catch (NumberFormatException exc) {
System.out.println(
"Unknown integer format");
}
}
}
View Code

异常被抛出后,程序控制就会立刻从try转移到catch中去。异常位置之后的语句不会执行。

Java笔记:异常处理Java笔记:异常处理
import java.util.Scanner;

class Solution {
public static void main(String[] args) {
Scanner in
= new Scanner(System.in);
String s
= in.nextLine();
String t
= in.nextLine();
try {
int a = Integer.parseInt(s);
int b = Integer.parseInt(t);
System.out.println(a
/ b);
}
catch (ArithmeticException exc) {
System.out.println(
"Divisor cannot be 0");
}
catch (NumberFormatException exc) {
System.out.println(
"Unknown integer format");
}
}
}
View Code

单块代码可能会出现多种异常情况,可通过指定多条catch语句来捕获所有可能出现的异常。当异常抛出时,会按顺序检查每条catch语句,直到遇到可以匹配的catch语句,之后会忽略剩余的catch语句。若异常无法遇到匹配的catch语句,将会无法被捕获,程序会因异常而中断。

当使用多条catch语句时,子类异常捕获必须位于所有超类之前。若超类异常捕获位于子类之前,那么子类异常将永远无法被捕获。

 

四、内置异常

在Java内置的异常类中,最常用的是RuntimeException的子类。

所有方法不需要指明会抛出这些异常,称为未经检查的异常。

 

四、自定义异常

Exception类没有定义任何方法,但继承了Throwable提供的方法。

可通过继承Exception来实现自定义异常,可通过重写toString方法来修改异常描述。

Java笔记:异常处理Java笔记:异常处理
import java.util.Scanner;

class MyException extends Exception {
MyException(String msg) {
super(msg);
}

@Override
public String toString() {
return "MyException: " + super.getMessage();
}
}

class Solution {
static int divide(int a, int b) throws MyException {
if (b == 0)
throw new MyException("Divisor cannot be 0");
return a / b;
}

public static void main(String[] args) {
Scanner in
= new Scanner(System.in);
int a = in.nextInt();
int b = in.nextInt();
try {
int res = divide(a, b);
System.out.println(res);
}
catch (MyException exc) {
System.out.println(exc);
}
}
}
View Code

 

五、链式异常

通过链式异常,可以为异常关联另一个异常。第二个异常是引发第一个异常的原因,称为引发异常或背后异常。可通过getCause方法获取当前异常的背后异常,通过initCause或构造函数关联背后异常,并且背后异常只能设置一次。

Java笔记:异常处理Java笔记:异常处理
class Solution {
static void throwerA() {
IndexOutOfBoundsException exc
= new IndexOutOfBoundsException("Index out of bounds");
exc.initCause(
new NullPointerException());
throw exc;
}

static void throwerB() throws Exception {
throw new Exception("Null pointer cause exception", new NullPointerException());
}

public static void main(String[] args) {
try {
throwerA();
}
catch (IndexOutOfBoundsException exc) {
System.out.println(exc.toString());
System.out.println(exc.getCause().toString());
}
try {
throwerB();
}
catch (Exception exc) {
System.out.println(exc.toString());
System.out.println(exc.getCause().toString());
}
}
}
View Code


六、多重捕获

可通过单独的catch语句捕获多个异常。

Java笔记:异常处理Java笔记:异常处理
import java.util.Scanner;

class Solution {
public static void main(String[] args) {
Scanner in
= new Scanner(System.in);
int a = in.nextInt();
int b = in.nextInt();
int[] nums = {1, 2, 3};
try {
int res = a / b;
nums[a]
= res;
}
catch (ArithmeticException | ArrayIndexOutOfBoundsException exc) {
System.out.println(exc.toString());
}
}
}
View Code