1. 异常的定义与体系结构
异常是程序运行过程中出现的非正常情况,会中断程序的正常执行流程。Java异常体系结构如下图所示:
Throwable
├── Error(系统级错误,如内存溢出)
└── Exception(可处理异常)
├── RuntimeException(运行时异常,如空指针)
└── 其他编译时异常(如IOException)
2. 异常的作用
-
调试辅助:通过异常信息快速定位问题根源
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "String.length()" because "str" is null
-
流程控制:作为特殊返回值传递错误状态
public void processFile() throws IOException { // 文件处理逻辑 }
3. 异常处理方式
3.1 JVM默认处理
-
打印异常信息(名称、原因、位置)
-
终止程序运行
-
示例现象:
Exception in thread "main" java.lang.ArithmeticException: / by zero at Main.main(Main.java:5)
3.2 try-catch捕获处理
基础语法:
try {
// 可能抛出异常的代码
} catch (ExceptionType1 e1) {
// 处理类型1异常
} catch (ExceptionType2 e2) {
// 处理类型2异常
} finally {
// 无论是否异常都会执行
}
关键要点:
-
多catch块顺序:子类异常在前,父类在后
-
JDK7+多异常捕获:
try { // code } catch (IOException | SQLException e) { e.printStackTrace(); }
-
finally块常用于资源释放
完整示例:
FileInputStream fis = null;
try {
fis = new FileInputStream("test.txt");
// 文件操作...
} catch (FileNotFoundException e) {
System.out.println("文件未找到: " + e.getMessage());
} finally {
if(fis != null) {
try { fis.close(); }
catch (IOException e) { /* 处理关闭异常 */ }
}
}
3.3 throws/throw抛出异常
关键字 | 位置 | 作用 |
---|---|---|
throws | 方法声明 | 声明可能抛出的异常类型 |
throw | 方法体内 | 主动抛出异常对象 |
throws示例:
public void readFile() throws IOException {
// 可能抛出IO异常的代码
}
throw示例:
public void setAge(int age) {
if(age < 0) {
throw new IllegalArgumentException("年龄不能为负数");
}
this.age = age;
}
编译时异常 vs 运行时异常:
-
编译时异常:必须处理(捕获或声明抛出)
-
运行时异常:通常由程序逻辑错误引起,可不处理
4. Throwable类核心方法
方法 | 输出示例 | 说明 |
---|---|---|
getMessage() | "/ by zero" | 异常详细信息 |
toString() | "java.lang.ArithmeticException: / by zero" | 简短描述 |
printStackTrace() | 完整堆栈跟踪信息 | 输出到标准错误流 |
示例使用:
try {
int result = 10 / 0;
} catch (ArithmeticException e) {
System.out.println(e.getMessage()); // / by zero
System.out.println(e.toString()); // java.lang.ArithmeticException: / by zero
e.printStackTrace(); // 完整堆栈信息
}
5. 自定义异常
实现步骤:
-
继承Exception(编译时异常)或RuntimeException(运行时异常)
-
添加构造方法
示例代码:
ublic class InvalidAgeException extends RuntimeException {
// 无参构造
public InvalidAgeException() {
super("年龄无效异常");
}
// 带参构造
public InvalidAgeException(String message) {
super(message);
}
}
// 使用示例
public class Person {
private int age;
public void setAge(int age) {
if(age < 0 || age > 150) {
throw new InvalidAgeException("无效年龄值: " + age);
}
this.age = age;
}
}
6. 异常处理最佳实践
-
精准捕获:避免捕获过于宽泛的Exception
-
资源管理:优先使用try-with-resources
try (FileInputStream fis = new FileInputStream("file.txt")) { // 自动资源管理 } catch (IOException e) { // 异常处理 }
-
异常包装:保留原始异常信息
catch (SQLException e) { throw new ServiceException("数据库操作失败", e); }
-
日志记录:使用日志框架代替printStackTrace()
-
避免空catch块:至少要记录异常信息
通过系统学习异常处理机制,开发者可以编写出更健壮、易维护的Java程序。正确处理异常不仅能提升系统稳定性,还能显著提高调试效率。