深入学习Java中throw和throws关键字的使用方法,掌握异常的抛出和声明机制
throw关键字用于在程序中主动抛出异常。当程序检测到错误条件时,可以使用throw语句创建并抛出一个异常对象。
// 语法格式
throw new ExceptionType("异常信息");
// 示例
if (age < 0) {
throw new IllegalArgumentException("年龄不能为负数: " + age);
}
public class ThrowExample {
/**
* 验证年龄是否合法
*/
public static void validateAge(int age) {
if (age < 0) {
// 使用throw主动抛出异常
throw new IllegalArgumentException("年龄不能为负数: " + age);
}
if (age > 150) {
throw new IllegalArgumentException("年龄不能超过150岁: " + age);
}
System.out.println("年龄验证通过: " + age + "岁");
}
/**
* 计算平方根
*/
public static double calculateSquareRoot(double number) {
if (number < 0) {
throw new ArithmeticException("不能计算负数的平方根: " + number);
}
return Math.sqrt(number);
}
public static void main(String[] args) {
try {
validateAge(25); // 正常执行
validateAge(-5); // 抛出异常
} catch (IllegalArgumentException e) {
System.out.println("捕获异常: " + e.getMessage());
}
}
}
throws关键字用于在方法签名中声明该方法可能抛出的异常类型。它告诉调用者这个方法可能会抛出哪些异常,调用者必须处理这些异常或继续向上抛出。
// 语法格式
public void methodName() throws ExceptionType1, ExceptionType2 {
// 方法体
}
// 示例
public void readFile(String filename) throws IOException {
// 可能抛出IOException的代码
}
import java.io.*;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class ThrowsExample {
/**
* 读取文件内容
*/
public static String readFile(String filename) throws IOException {
BufferedReader reader = new BufferedReader(new FileReader(filename));
StringBuilder content = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
content.append(line).append("\n");
}
reader.close();
return content.toString();
}
/**
* 解析日期字符串
*/
public static Date parseDate(String dateStr, String pattern) throws ParseException {
SimpleDateFormat formatter = new SimpleDateFormat(pattern);
return formatter.parse(dateStr);
}
/**
* 处理多个异常的方法
*/
public static void performOperation(String operation)
throws IOException, ParseException, SQLException {
switch (operation) {
case "file":
readFile("test.txt");
break;
case "date":
parseDate("invalid-date", "yyyy-MM-dd");
break;
case "database":
connectDatabase("", "user", "pass");
break;
}
}
public static void main(String[] args) {
// 调用者必须处理异常
try {
String content = readFile("test.txt");
System.out.println("文件内容: " + content);
} catch (IOException e) {
System.out.println("文件操作异常: " + e.getMessage());
}
}
}
特性 | throw | throws |
---|---|---|
位置 | 方法体内 | 方法签名中 |
作用 | 抛出异常 | 声明异常 |
数量 | 一次只能抛出一个 | 可以声明多个 |
语法 | throw + 异常对象 | throws + 异常类型 |
执行时机 | 运行时执行 | 编译时检查 |
后续代码 | 不会执行 | 正常执行 |
public class ThrowVsThrowsExample {
/**
* 使用throw主动抛出异常的方法
*/
public static void validateScore(int score) {
// 使用throw主动抛出异常
if (score < 0 || score > 100) {
throw new IllegalArgumentException("分数必须在0-100之间: " + score);
}
System.out.println("分数有效: " + score);
}
/**
* 使用throws声明可能抛出异常的方法
*/
public static double safeDivide(double dividend, double divisor) throws ArithmeticException {
if (divisor == 0) {
throw new ArithmeticException("除数不能为零");
}
return dividend / divisor;
}
/**
* 同时使用throw和throws的方法
*/
public static String processText(String text, int maxLength)
throws IllegalArgumentException, RuntimeException {
// 参数验证,使用throw抛出异常
if (text == null) {
throw new IllegalArgumentException("文本不能为null");
}
if (maxLength <= 0) {
throw new IllegalArgumentException("最大长度必须大于0");
}
// 业务逻辑处理
if (text.length() > maxLength) {
if (maxLength < 10) {
throw new RuntimeException("文本太长且最大长度太小,无法处理");
}
return text.substring(0, maxLength) + "...";
}
return text;
}
}
当方法抛出异常时,异常会沿着调用栈向上传播,直到被捕获处理或到达程序顶层。
public class ExceptionPropagationExample {
/**
* 方法链中的异常传播示例
*/
public static void methodA(int value) throws Exception {
System.out.println("方法A开始执行");
methodB(value); // 调用可能抛出异常的方法
System.out.println("方法A执行完成");
}
public static void methodB(int value) throws Exception {
System.out.println("方法B开始执行");
methodC(value); // 继续传播异常
System.out.println("方法B执行完成");
}
public static void methodC(int value) throws Exception {
System.out.println("方法C开始执行");
if (value < 0) {
throw new Exception("方法C: 值不能为负数 " + value);
}
System.out.println("方法C执行完成,值: " + value);
}
public static void main(String[] args) {
try {
methodA(5); // 正常执行
methodA(-1); // 异常传播
} catch (Exception e) {
System.out.println("在main方法中捕获异常: " + e.getMessage());
}
}
}
// 尽早抛出异常
if (user == null) {
throw new IllegalArgumentException("用户不能为null");
}
// 提供有意义的异常信息
throw new IllegalArgumentException(
"年龄必须在0-150之间,当前值: " + age);
// 使用具体的异常类型
throw new FileNotFoundException("文件未找到: " + filename);
// 保留异常链
try {
// 一些操作
} catch (IOException e) {
throw new ServiceException("服务调用失败", e);
}
// 忽略异常
try {
riskyOperation();
} catch (Exception e) {
// 什么都不做 - 错误做法
}
// 异常信息不明确
throw new Exception("错误");
// 过度使用检查异常
public void setAge(int age) throws InvalidAgeException {
if (age < 0) throw new InvalidAgeException();
}
// 丢失异常信息
try {
operation();
} catch (SpecificException e) {
throw new RuntimeException("操作失败");
}