throw 关键字
概述
throw
关键字用于手动抛出异常,可以抛出系统定义的异常或自定义异常。
语法格式
throw new ExceptionType("异常消息");
throw exceptionObject;
基本用法
public class ThrowExample {
public static void validateAge(int age) {
if (age < 0) {
throw new IllegalArgumentException("年龄不能为负数");
}
if (age > 150) {
throw new IllegalArgumentException("年龄不能超过150岁");
}
System.out.println("年龄验证通过: " + age);
}
public static double divide(double a, double b) {
if (b == 0) {
throw new ArithmeticException("除数不能为0");
}
return a / b;
}
public static void main(String[] args) {
try {
validateAge(25); // 正常
validateAge(-5); // 抛出异常
} catch (IllegalArgumentException e) {
System.out.println("参数错误: " + e.getMessage());
}
try {
double result = divide(10, 0);
System.out.println("结果: " + result);
} catch (ArithmeticException e) {
System.out.println("计算错误: " + e.getMessage());
}
}
}
自定义异常
// 自定义检查异常
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; }
}
// 自定义运行时异常
class InvalidAccountException extends RuntimeException {
public InvalidAccountException(String message) {
super(message);
}
public InvalidAccountException(String message, Throwable cause) {
super(message, cause);
}
}
public class CustomExceptionExample {
public static void withdraw(double balance, double amount)
throws InsufficientBalanceException {
if (amount <= 0) {
throw new InvalidAccountException("取款金额必须大于0");
}
if (amount > balance) {
throw new InsufficientBalanceException(balance, amount);
}
System.out.println("取款成功:" + amount + ",剩余余额:" + (balance - amount));
}
public static void main(String[] args) {
try {
withdraw(1000, 500); // 正常取款
withdraw(1000, 1500); // 余额不足
} catch (InsufficientBalanceException e) {
System.out.println("取款失败: " + e.getMessage());
System.out.println("当前余额: " + e.getBalance());
System.out.println("尝试金额: " + e.getAmount());
}
try {
withdraw(1000, -100); // 无效金额
} catch (InvalidAccountException e) {
System.out.println("账户操作错误: " + e.getMessage());
} catch (InsufficientBalanceException e) {
System.out.println("余额不足: " + e.getMessage());
}
}
}
异常链
import java.io.*;
public class ExceptionChainExample {
public static void readConfiguration(String filename) throws Exception {
try {
FileInputStream fis = new FileInputStream(filename);
// 读取配置文件
fis.close();
} catch (FileNotFoundException e) {
// 包装原始异常,创建异常链
throw new Exception("配置文件加载失败: " + filename, e);
} catch (IOException e) {
throw new Exception("读取配置文件时发生IO错误", e);
}
}
public static void initializeApplication() throws Exception {
try {
readConfiguration("app.properties");
} catch (Exception e) {
// 再次包装异常
throw new Exception("应用程序初始化失败", e);
}
}
public static void main(String[] args) {
try {
initializeApplication();
} catch (Exception e) {
System.out.println("最终错误: " + e.getMessage());
// 打印异常链
Throwable cause = e.getCause();
while (cause != null) {
System.out.println("原因: " + cause.getMessage());
cause = cause.getCause();
}
System.out.println("\n完整堆栈跟踪:");
e.printStackTrace();
}
}
}
业务逻辑中的异常抛出
import java.util.*;
// 用户管理系统示例
public class UserManagementExample {
// 自定义业务异常
static class UserNotFoundException extends Exception {
public UserNotFoundException(String userId) {
super("用户未找到: " + userId);
}
}
static class DuplicateUserException extends Exception {
public DuplicateUserException(String userId) {
super("用户已存在: " + userId);
}
}
static class InvalidUserDataException extends RuntimeException {
public InvalidUserDataException(String message) {
super(message);
}
}
// 用户类
static class User {
private String id;
private String name;
private String email;
public User(String id, String name, String email) {
this.id = id;
this.name = name;
this.email = email;
}
// Getters
public String getId() { return id; }
public String getName() { return name; }
public String getEmail() { return email; }
@Override
public String toString() {
return "User{id='" + id + "', name='" + name + "', email='" + email + "'}";
}
}
// 用户服务
static class UserService {
private Map<String, User> users = new HashMap<>();
public void createUser(String id, String name, String email)
throws DuplicateUserException {
// 数据验证
validateUserData(id, name, email);
// 检查用户是否已存在
if (users.containsKey(id)) {
throw new DuplicateUserException(id);
}
User user = new User(id, name, email);
users.put(id, user);
System.out.println("用户创建成功: " + user);
}
public User findUser(String id) throws UserNotFoundException {
if (id == null || id.trim().isEmpty()) {
throw new InvalidUserDataException("用户ID不能为空");
}
User user = users.get(id);
if (user == null) {
throw new UserNotFoundException(id);
}
return user;
}
public void deleteUser(String id) throws UserNotFoundException {
User user = findUser(id); // 可能抛出UserNotFoundException
users.remove(id);
System.out.println("用户删除成功: " + user);
}
private void validateUserData(String id, String name, String email) {
if (id == null || id.trim().isEmpty()) {
throw new InvalidUserDataException("用户ID不能为空");
}
if (name == null || name.trim().isEmpty()) {
throw new InvalidUserDataException("用户名不能为空");
}
if (email == null || !email.contains("@")) {
throw new InvalidUserDataException("邮箱格式不正确");
}
}
public void listUsers() {
if (users.isEmpty()) {
System.out.println("没有用户");
} else {
System.out.println("用户列表:");
users.values().forEach(System.out::println);
}
}
}
public static void main(String[] args) {
UserService service = new UserService();
try {
// 正常创建用户
service.createUser("001", "张三", "zhangsan@example.com");
service.createUser("002", "李四", "lisi@example.com");
// 尝试创建重复用户
service.createUser("001", "王五", "wangwu@example.com");
} catch (DuplicateUserException e) {
System.out.println("创建失败: " + e.getMessage());
} catch (InvalidUserDataException e) {
System.out.println("数据验证失败: " + e.getMessage());
}
try {
// 查找用户
User user = service.findUser("001");
System.out.println("找到用户: " + user);
// 查找不存在的用户
service.findUser("999");
} catch (UserNotFoundException e) {
System.out.println("查找失败: " + e.getMessage());
} catch (InvalidUserDataException e) {
System.out.println("参数错误: " + e.getMessage());
}
try {
// 删除用户
service.deleteUser("002");
// 删除不存在的用户
service.deleteUser("999");
} catch (UserNotFoundException e) {
System.out.println("删除失败: " + e.getMessage());
}
// 显示剩余用户
service.listUsers();
}
}
最佳实践
public class ThrowBestPractices {
// 1. 抛出有意义的异常
public static void processFile(String filename) {
if (filename == null) {
throw new IllegalArgumentException("文件名不能为null");
}
if (filename.trim().isEmpty()) {
throw new IllegalArgumentException("文件名不能为空");
}
// 处理文件...
}
// 2. 保持异常消息清晰
public static void withdraw(double balance, double amount) {
if (amount <= 0) {
throw new IllegalArgumentException(
String.format("取款金额无效: %.2f (必须大于0)", amount));
}
if (amount > balance) {
throw new IllegalStateException(
String.format("余额不足: 当前%.2f, 尝试取款%.2f", balance, amount));
}
}
// 3. 在合适的抽象级别抛出异常
public static void saveUserData(String userData) throws DataPersistenceException {
try {
// 底层数据库操作
performDatabaseOperation(userData);
} catch (SQLException e) {
// 将低级别的数据库异常转换为业务级别的异常
throw new DataPersistenceException("保存用户数据失败", e);
}
}
// 4. 避免过度使用异常
public static boolean isValidEmail(String email) {
// 好的做法:返回boolean而不是抛出异常
return email != null && email.contains("@");
}
// 避免这样做:
// public static void validateEmail(String email) {
// if (!email.contains("@")) {
// throw new IllegalArgumentException("邮箱格式不正确");
// }
// }
// 模拟方法
private static void performDatabaseOperation(String data) throws SQLException {
throw new SQLException("模拟数据库错误");
}
// 自定义异常类
static class DataPersistenceException extends Exception {
public DataPersistenceException(String message, Throwable cause) {
super(message, cause);
}
}
static class SQLException extends Exception {
public SQLException(String message) {
super(message);
}
}
}
throw关键字是Java异常处理的重要组成部分,正确使用它可以让程序的错误处理更加清晰和健壮。