Java异常处理机制
Java异常处理机制
Java是采用面向对象的方式来处理异常的。处理过程:
- 抛出异常:在执行一个方法时,如果发生异常,则这个方法生成代表该异常的一个对象,停止当前执行路径,并把异常对象提交给JRE。
- 捕获异常:JRE得到该异常后,寻找相应的代码来处理该异常。JRE在方法的调用栈中查找,从生成异常的方法开始回溯,直到找到相应的异常处理代码为止。
异常的分类
- java.lang.Throwable
- Error:Error是程序无法处理的错误,表示运行应用程序中较严重问题。大多数错误与代码编写者执行的操作无关,而表示代码运行时 JVM(Java 虚拟机)出现的问题。 Error表明系统JVM已经处于不可恢复的崩溃状态中。我们不需要管它。
- Exception:Exception是程序本身能够处理的异常,Exception类是所有异常类的父类,其子类对应了各种各样可能出现的异常事件。 通常Java的异常可分为:
- RuntimeException 运行时异常:这类异常通常是由编程错误导致的,所以在编写程序时,并不要求必须使用异常处理机制来处理这类异常,经常需要通过增加“逻辑处理来避免这些异常”。
- ArithmeticException异常:试图除以0
- NullPointerException异常:空指针
- ClassCastException异常:类型转换异常
- ArrayIndexOutOfBoundsException异常:数组下标越界异常
- NumberFormatException异常:数字格式异常
- CheckedException 已检查异常:所有不是RuntimeException的异常,统称为Checked Exception,又被称为“已检查异常”,如IOException、SQLException等以及用户自定义的Exception异常。 这类异常在编译时就必须做出处理,否则无法通过编译。
- RuntimeException 运行时异常:这类异常通常是由编程错误导致的,所以在编写程序时,并不要求必须使用异常处理机制来处理这类异常,经常需要通过增加“逻辑处理来避免这些异常”。

捕获异常

-
try:
当任意一条语句产生异常时,就会跳过该条语句中后面的代码。代码中可能会产生并抛出一种或几种类型的异常对象,它后面的catch语句要分别对这些异常做相应的处理。一个try语句必须带有至少一个catch语句块或一个finally语句块 。
-
catch:
每个try语句块可以伴随一个或多个catch语句,用于处理可能产生的不同类型的异常对象。常用方法,这些方法均继承自Throwable类:
- toString ()方法,显示异常的类名和产生异常的原因
- getMessage()方法,只显示产生异常的原因,但不显示类名。
- printStackTrace()方法,用来跟踪异常事件发生时堆栈的内容。
如果异常类之间有继承关系,在顺序安排上需注意。越是顶层的类,越放在下面,再不然就直接把多余的catch省略掉。 也就是先捕获子类异常再捕获父类异常。
-
finally:不管是否发生了异常,都必须要执行
- 即使try和catch块中存在return语句,finally语句也会执行。是在执行完finally语句后再通过return退出。
- finally语句块只有一种情况是不会执行的,那就是在执行finally之前遇到了System.exit(0)结束程序运行。
典型示例:
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class Test8 {
public static void main(String[] args) {
FileReader reader = null;
try {
reader = new FileReader("d:/a.txt");
char c = (char) reader.read();
char c2 = (char) reader.read();
System.out.println("" + c + c2);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (reader != null) {
reader.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
声明异常
当CheckedException产生时,不一定立刻处理它,可以再把异常throws出去。
- 如果一个方法中可能产生某种异常,但是并不能确定如何处理这种异常,则应根据异常规范在方法的首部声明该方法可能抛出的异常。
- 如果一个方法抛出多个已检查异常,就必须在方法的首部列出所有的异常,之间以逗号隔开。
典型示例:
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class Test9 {
public static void main(String[] args) {
try {
readFile("joke.txt");
} catch (FileNotFoundException e) {
System.out.println("所需文件不存在!");
} catch (IOException e) {
System.out.println("文件读写错误!");
}
}
public static void readFile(String fileName) throws FileNotFoundException,
IOException {
FileReader in = new FileReader(fileName);
int tem = 0;
try {
tem = in.read();
while (tem != -1) {
System.out.print((char) tem);
tem = in.read();
}
} finally {
in.close();
}
}
}
自定义异常
自定义异常类只需要继承Exception类或RuntimeException类
- 继承Exception类,则为受检查异常,必须对其进行处理。
- 继承运行时异常RuntimeException类,则可以不处理。
习惯上,自定义异常类应该包含2个构造器:一个是默认的构造器,另一个是带有详细信息的构造器。
示例:
/**IllegalAgeException:非法年龄异常,继承Exception类*/
class IllegalAgeException extends Exception {
//默认构造器
public IllegalAgeException() {
}
//带有详细信息的构造器,信息存储在message中
public IllegalAgeException(String message) {
super(message);
}
}
class Person {
private String name;
private int age;
public void setName(String name) {
this.name = name;
}
public void setAge(int age) throws IllegalAgeException {
if (age < 0) {
throw new IllegalAgeException("人的年龄不应该为负数");
}
this.age = age;
}
public String toString() {
return "name is " + name + " and age is " + age;
}
}
public class TestMyException {
public static void main(String[] args) {
Person p = new Person();
try {
p.setName("Lincoln");
p.setAge(-1);
} catch (IllegalAgeException e) {
e.printStackTrace();
System.exit(-1);
}
System.out.println(p);
}
}
使用异常机制的建议
- 要避免使用异常处理代替错误处理,这样会降低程序的清晰性,并且效率低下。
- 处理异常不可以代替简单测试---只在异常情况下使用异常机制。
- 不要进行小粒度的异常处理---应该将整个任务包装在一个try语句块中。
- 异常往往在高层处理。
try-with-resource
在处理流、文件等系统资源时,要在finally中写大量关闭语句,甚至关闭资源的代码竟然比业务代码还要多。为了解决这个问题在Java 1.7中新增的try-with-resource语法糖来打开资源。用法如下:
try (创建流对象语句,如果多个,使用';'隔开) {
// 读写数据
} catch (IOException e) {
e.printStackTrace();
}
示例可参见转换流那部分 。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了