Java throw与throws #

一、throw关键字 #

1.1 概念 #

throw用于手动抛出异常对象。

1.2 基本语法 #

java
throw new 异常类型("异常信息");

1.3 使用示例 #

java
public void setAge(int age) {
    if (age < 0 || age > 150) {
        throw new IllegalArgumentException("年龄必须在0-150之间");
    }
    this.age = age;
}

1.4 抛出不同类型异常 #

java
// 抛出运行时异常
public void checkNotNull(Object obj) {
    if (obj == null) {
        throw new NullPointerException("对象不能为空");
    }
}

// 抛出检查异常
public void readFile(String path) throws FileNotFoundException {
    if (path == null) {
        throw new FileNotFoundException("文件路径不能为空");
    }
}

二、throws关键字 #

2.1 概念 #

throws用于声明方法可能抛出的异常。

2.2 基本语法 #

java
返回类型 方法名(参数列表) throws 异常类型1, 异常类型2 {
    // 方法体
}

2.3 使用示例 #

java
public void readFile(String path) throws FileNotFoundException, IOException {
    FileInputStream fis = new FileInputStream(path);
    // 读取操作
}

2.4 声明多个异常 #

java
public void copyFile(String src, String dest) 
        throws FileNotFoundException, IOException {
    try (FileInputStream fis = new FileInputStream(src);
         FileOutputStream fos = new FileOutputStream(dest)) {
        // 复制操作
    }
}

三、throw与throws区别 #

throw throws
抛出异常对象 声明异常类型
在方法体内使用 在方法签名上使用
只能抛出一个异常 可以声明多个异常
抛出异常后方法结束 只是声明,不处理

3.1 对比示例 #

java
// throw:抛出异常
public void method1() {
    throw new RuntimeException("错误");
}

// throws:声明异常
public void method2() throws IOException {
    // 可能抛出IOException
}

// 组合使用
public void method3() throws IllegalArgumentException {
    if (invalid) {
        throw new IllegalArgumentException("参数无效");
    }
}

四、异常传递 #

4.1 异常链 #

java
public void method1() throws Exception {
    method2();
}

public void method2() throws Exception {
    method3();
}

public void method3() throws Exception {
    throw new Exception("原始异常");
}

4.2 异常处理传递 #

java
public void outer() {
    try {
        inner();
    } catch (IOException e) {
        System.out.println("捕获到异常: " + e.getMessage());
    }
}

public void inner() throws IOException {
    throw new IOException("内部异常");
}

五、重写方法的异常声明 #

5.1 规则 #

  • 子类方法可以抛出与父类相同的异常
  • 子类方法可以抛出父类异常的子类
  • 子类方法可以不抛出异常
  • 子类方法不能抛出父类没有的检查异常

5.2 示例 #

java
class Parent {
    public void method() throws IOException { }
}

class Child extends Parent {
    // 正确:抛出相同异常
    @Override
    public void method() throws IOException { }
    
    // 正确:抛出子类异常
    // @Override
    // public void method() throws FileNotFoundException { }
    
    // 正确:不抛出异常
    // @Override
    // public void method() { }
    
    // 错误:抛出父类没有的检查异常
    // @Override
    // public void method() throws SQLException { }
    
    // 正确:可以抛出运行时异常
    // @Override
    // public void method() throws RuntimeException { }
}

六、最佳实践 #

6.1 合理选择异常类型 #

java
// 参数校验:使用运行时异常
public void setName(String name) {
    if (name == null || name.isEmpty()) {
        throw new IllegalArgumentException("姓名不能为空");
    }
    this.name = name;
}

// 业务异常:使用检查异常
public void withdraw(double amount) throws InsufficientBalanceException {
    if (amount > balance) {
        throw new InsufficientBalanceException("余额不足");
    }
    balance -= amount;
}

6.2 提供有意义的异常信息 #

java
// 不推荐
throw new IllegalArgumentException("错误");

// 推荐
throw new IllegalArgumentException("年龄 " + age + " 不在有效范围内(0-150)");

6.3 保留原始异常 #

java
public void loadData() throws DataLoadException {
    try {
        readFromFile();
    } catch (IOException e) {
        throw new DataLoadException("数据加载失败", e);
    }
}

6.4 早失败 #

java
public void process(String input) {
    // 尽早检查和抛出异常
    if (input == null) {
        throw new IllegalArgumentException("输入不能为空");
    }
    if (input.isEmpty()) {
        throw new IllegalArgumentException("输入不能为空字符串");
    }
    
    // 正常处理
    doProcess(input);
}

七、总结 #

关键字 用途 位置
throw 抛出异常对象 方法体内
throws 声明异常类型 方法签名

throw与throws要点:

  • throw用于抛出异常对象
  • throws用于声明方法可能抛出的异常
  • 检查异常必须处理或声明
  • 运行时异常可选处理
  • 重写方法时异常声明有规则限制
最后更新:2026-03-26