Exception与Error
Java程序在执行过程中所发生的异常事件可分为两类:
- Error(错误):Java虚拟机无法解决的严重问题。是系统中的错误,大多数与程序员的操作无关,程序员是不能改变和处理的,不需要关心这类错误。例如:StackOverflowError(栈溢出)和OOM(内存溢出)
- Exception(异常): 在程序运行期间,发生的不被期望的事件,阻止了程序按照程序员的预期正常执行(开发过程中的语法错误和逻辑错误不是异常)。可以使用针对性的代码进行处理。例如:空指针访问、试图读取不存在的文件、网络连接中断、数组角标越界、非法参数
异常分类
- 检查型异常:最具代表性异常是用户错误或问题引起的异常,这是程序员无法预见的。例如用户要打开一个不存在的文件时引发的异常,这些异常在编译时不能被简单地忽略
- 运行时异常:是可能被程序员避免的异常,与检查性异常相反,运行时异常可以在编译时忽略
异常示例
-
java.lang.StackOverflowError 栈堆异常
Javapublic class Demo01 { public static void main(String[] args) { new Demo01().a(); //创建一个Demo01类的实例,并调用其a方法。 } public void a(){ b(); } public void b(){ a(); } } //在方法a中,调用了方法b;在方法b中,又调回了方法a。如此反复,陷入了一个无限循环。
-
java.lang.ArithmeticException 算数运算异常
Javapublic class Demo02 { public static void main(String[] args) { System.out.println(11/0); } }
异常体系结构
Java标准库内建了一些通用的异常,这些类以Throwable为顶层父类,Throwable又派生出Error类和Exception类。
异常处理机制
捕获异常
当程序中抛出一个异常后,如果该异常没有被捕获和处理,程序将终止。 可以使用try-catch
语句来捕获异常。try
块用于包含可能抛出异常的代码,而catch
块用于捕获并处理异常。
语法格式
java
try {
// 可能会抛出异常的代码
} catch (ExceptionType1 e) {
// 处理ExceptionType1异常的代码
} catch (ExceptionType2 e) {
// 处理ExceptionType2异常的代码
}finally {
// 可选的finally块,无论是否发生了异常。这个块里的代码总是会被执行,除非程序中止
//用于在发生异常或未发生异常时执行清理工作
}
在上述代码中:
catch
块用于捕获并处理在try
块中抛出的异常。可以有一个或多个catch
块,每个块处理一种特定类型的异常。在每个catch
块中,可以编写处理特定异常的代码。例如,可能想要记录异常信息,或者尝试以某种方式恢复程序的执行ExceptionType1
和ExceptionType2
是Java中预定义的异常类或自定义的异常类。它们表示特定类型的异常e
是catch
块中声明的变量,表示捕获的异常对象。可以使用这个变量来访问有关异常的信息,如异常的消息或堆栈跟踪
getMessage() 方法
getMessage() 方法定义在 Throwable
类中,因此它可以在任何从 Throwable
继承的类(如异常类)中直接使用,而不需要单独定义。当捕获到异常时,可以直接调用异常对象的 getMessage()
方法,以获取异常的描述信息
应用:当异常被捕获时,可以通过catch
块中的参数e
(或者自定义的异常变量名)来访问异常对象。e.getMessage()
方法将返回一个字符串,其中包含有关异常的描述或详细信息。
示例
java
try {
int[] arr = new int[5];
arr[10] = 100; // 这将抛出一个ArrayIndexOutOfBoundsException异常
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("数组越界异常: " + e.getMessage());
//这个异常被第一个catch块捕获,并输出一条包含异常消息的错误信息
} catch (Exception e) {
System.out.println("其他异常: " + e.getMessage());
//如果try块中的代码抛出其他类型的异常,它将被第二个catch块捕获,并输出一条包含异常消息的错误信息
}
快捷键
- 按下
Ctrl+Alt+T
快捷键,打开代码生成菜单 - 在菜单中选择"Surround With"选项
- 在弹出的列表中选择"Try/Catch"选项
- 按下Enter键,IDEA会自动在光标所在行的下一行插入一个try-catch代码块
抛出异常
除了捕获异常,还可以在程序中主动抛出异常 在Java中,可以使用throw
关键字来显式地抛出一个异常。在try-catch
语句中,一旦使用throw
抛出一个异常,程序控制将立即转到最近的能够处理该异常的catch
块
语法格式
Java
throw new 异常类型(参数); //参数 是可选的,用于初始化异常对象
当使用throw
语句抛出异常后,程序将立即停止执行后面的代码,并跳转到能够处理该异常的catch
块。如果没有找到合适的catch
块来处理异常,程序将终止
示例
java
public class Example {
public static void main(String[] args) {
try {
int[] arr = new int[5];
throw new ArrayIndexOutOfBoundsException("数组越界异常");
arr[10] = 100; // 这行代码不会被执行,因为throw语句已经抛出了异常
} catch (ArrayIndexOutOfBoundsException e) { //程序控制立即转到第一个catch块
System.out.println("捕获到数组越界异常: " + e.getMessage());
//并输出一条包含异常消息的错误信息
} catch (Exception e) {
System.out.println("捕获到其他异常: " + e.getMessage());
}
}
}
自定义异常
- 创建自定义异常类,继承自Exception或Exception子类
- 在方法中通过throw关键字抛出异常对象
- 如果在抛出异常的方法中处理异常,可以使用try-catch语句捕获并处理;否则在方法的声明处通过throws关键字指明要抛出给方法调用者的异常
- 在出现异常方法的调用者中捕获并处理异常
Java
public class Demo02 {
public static void main(String[] args) {
try {
test(11);
} catch (MyException e) {
System.out.println("MyException->" + e); // 打印 MyException->MyException{detail=11}
//这里使用了异常对象e的toString()方法,该方法覆盖了从Exception类继承的方法,返回一个描述异常的字符串
}
}
public static void test(int a) throws MyException {
//定义了一个名为test的公共静态方法,它接受一个整数参数并可能抛出一个MyException异常
if (a>10){
throw new MyException(a);
//抛出一个新的MyException异常,并传递参数a作为详细信息。这将导致程序跳回到调用此方法的主方法中,并执行相应的catch块来处理这个异常
}
}
}
class MyException extends Exception{ //自定义异常类MyException的定义
private int detail;
public MyException(int detail) {
this.detail = detail;
}
@Override
public String toString() { // 重写Exception类的toString方法,返回异常的字符串表示形式
return "MyException{" + "detail=" + detail + '}'; // 返回包含detail值的字符串
}
}