异常处理
异常处理让程序更健壮,本课学习Java中的异常处理机制。
什么是异常
异常是程序运行时发生的错误。
异常分类
TEXT
Throwable
├── Error(严重错误,程序无法处理)
│ ├── OutOfMemoryError
│ └── StackOverflowError
└── Exception(异常,程序可以处理)
├── 受检异常(必须处理)
│ ├── IOException
│ └── SQLException
└── 非受检异常(RuntimeException)
├── NullPointerException
├── ArrayIndexOutOfBoundsException
└── NumberFormatException
try-catch
语法
JAVA
try {
// 可能抛出异常的代码
} catch (异常类型 变量名) {
// 处理异常
}
示例:基本异常处理
JAVA
public class TryCatchDemo {
public static void main(String[] args) {
try {
int result = 10 / 0;
System.out.println(result);
} catch (ArithmeticException e) {
System.out.println("发生算术异常:" + e.getMessage());
}
System.out.println("程序继续执行");
}
}
输出:
TEXT
发生算术异常:/ by zero
程序继续执行
多个catch
JAVA
try {
// 可能抛出多种异常的代码
} catch (异常类型1 e1) {
// 处理异常1
} catch (异常类型2 e2) {
// 处理异常2
} catch (Exception e) {
// 处理其他异常
}
示例:多个catch
JAVA
public class MultiCatch {
public static void main(String[] args) {
try {
String s = "abc";
int num = Integer.parseInt(s);
int result = 10 / num;
} catch (NumberFormatException e) {
System.out.println("数字格式错误:" + e.getMessage());
} catch (ArithmeticException e) {
System.out.println("算术错误:" + e.getMessage());
} catch (Exception e) {
System.out.println("其他错误:" + e.getMessage());
}
}
}
try-catch-finally
finally块无论是否发生异常都会执行。
语法
JAVA
try {
// 可能抛出异常的代码
} catch (异常类型 e) {
// 处理异常
} finally {
// 无论是否异常都会执行
}
示例:finally
JAVA
public class FinallyDemo {
public static void main(String[] args) {
try {
System.out.println("try块");
int result = 10 / 0;
} catch (ArithmeticException e) {
System.out.println("catch块");
} finally {
System.out.println("finally块");
}
}
}
输出:
TEXT
try块
catch块
finally块
示例:资源释放
JAVA
import java.io.*;
public class ResourceDemo {
public static void main(String[] args) {
FileReader reader = null;
try {
reader = new FileReader("test.txt");
// 读取文件
} catch (FileNotFoundException e) {
System.out.println("文件不存在");
} finally {
// 释放资源
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
try-with-resources
Java 7引入,自动关闭资源。
语法
JAVA
try (资源类型 变量 = new 资源()) {
// 使用资源
} catch (异常类型 e) {
// 处理异常
}
示例:try-with-resources
JAVA
import java.io.*;
public class TryWithResources {
public static void main(String[] args) {
// 自动关闭资源
try (BufferedReader reader = new BufferedReader(new FileReader("test.txt"))) {
String line = reader.readLine();
System.out.println(line);
} catch (IOException e) {
System.out.println("读取错误:" + e.getMessage());
}
// reader自动关闭,不需要finally
}
}
throw和throws
throw:抛出异常
JAVA
public static int divide(int a, int b) {
if (b == 0) {
throw new ArithmeticException("除数不能为0");
}
return a / b;
}
throws:声明异常
JAVA
public static void readFile(String path) throws FileNotFoundException {
FileReader reader = new FileReader(path);
}
示例:throw和throws
JAVA
public class ThrowDemo {
public static int divide(int a, int b) {
if (b == 0) {
throw new ArithmeticException("除数不能为0");
}
return a / b;
}
public static void validateAge(int age) {
if (age < 0 || age > 150) {
throw new IllegalArgumentException("年龄不合法:" + age);
}
}
public static void main(String[] args) {
try {
System.out.println(divide(10, 0));
} catch (ArithmeticException e) {
System.out.println(e.getMessage()); // 除数不能为0
}
try {
validateAge(-5);
} catch (IllegalArgumentException e) {
System.out.println(e.getMessage()); // 年龄不合法:-5
}
}
}
自定义异常
步骤
- 继承Exception或RuntimeException
- 提供构造方法
示例:自定义异常
JAVA
// 自定义异常类
public class InsufficientBalanceException extends Exception {
private double balance;
private double amount;
public InsufficientBalanceException(double balance, double amount) {
super("余额不足:余额" + balance + ",取款" + amount);
this.balance = balance;
this.amount = amount;
}
public double getBalance() {
return balance;
}
public double getAmount() {
return amount;
}
}
// 使用自定义异常
public class BankAccount {
private double balance;
public BankAccount(double balance) {
this.balance = balance;
}
public void withdraw(double amount) throws InsufficientBalanceException {
if (amount > balance) {
throw new InsufficientBalanceException(balance, amount);
}
balance -= amount;
System.out.println("取款成功,余额:" + balance);
}
public static void main(String[] args) {
BankAccount account = new BankAccount(1000);
try {
account.withdraw(500); // 取款成功,余额:500.0
account.withdraw(800); // 抛出异常
} catch (InsufficientBalanceException e) {
System.out.println(e.getMessage());
System.out.println("余额:" + e.getBalance());
System.out.println("取款:" + e.getAmount());
}
}
}
常见异常
| 异常 | 说明 | 原因 |
|---|---|---|
NullPointerException |
空指针 | 对象为null时调用方法 |
ArrayIndexOutOfBoundsException |
数组越界 | 访问不存在的索引 |
NumberFormatException |
数字格式错误 | 字符串转数字失败 |
ClassCastException |
类型转换错误 | 向下转型类型不匹配 |
ArithmeticException |
算术错误 | 除以0 |
FileNotFoundException |
文件不存在 | 文件路径错误 |
IOException |
IO错误 | 读写文件失败 |
异常处理原则
| 原则 | 说明 |
|---|---|
| 具体异常优先 | 先catch具体异常,再catch通用异常 |
| 不要忽略异常 | 至少打印日志 |
| finally释放资源 | 或用try-with-resources |
| 不要用异常控制流程 | 异常是处理错误的,不是控制流程的 |
❓ 常见问题
Q Error和Exception有什么区别?
A Error是严重错误,程序无法处理。Exception是异常,程序可以捕获处理。
Q 受检异常和非受检异常有什么区别?
A 受检异常必须处理(try-catch或throws)。非受检异常可以不处理。
Q 什么时候自定义异常?
A 需要区分业务异常类型时,如余额不足、用户不存在等。
📖 小节
- 异常是程序运行时的错误
- try-catch捕获异常,finally释放资源
- throw抛出异常,throws声明异常
- try-with-resources自动关闭资源
- 自定义异常继承Exception或RuntimeException
📝 作业
- 异常处理: 编写方法读取文件,处理文件不存在和读取错误
- 自定义异常: 定义AgeOutOfBoundsException,验证年龄
- 资源管理: 用try-with-resources实现文件复制
下一课
下一课我们将学习 实战:面向对象,综合运用面向对象知识。



