方法声明中的 throws 子句

Java 检查的异常机制要求程序员声明某些方法可以抛出指定的已检查异常。这是使用 throws 子句完成的。例如:

public class OddNumberException extends Exception { // a checked exception
}

public void checkEven(int number) throws OddNumberException {
    if (number % 2 != 0) {
        throw new OddNumberException();
    }
}

throws OddNumberException 声明对 checkEven 的调用可能会抛出 OddNumberException 类型的异常。

throws 子句可以声明类型列表,并且可以包括未经检查的异常以及已检查的异常。

public void checkEven(Double number) 
        throws OddNumberException, ArithmeticException {
    if (!Double.isFinite(number)) {
        throw new ArithmeticException("INF or NaN");
    } else if (number % 2 != 0) {
        throw new OddNumberException();
    }
}

将未经检查的异常声明为抛出的重点是什么?

方法声明中的 throws 子句有两个用途:

  1. 它告诉编译器抛出了哪些异常,以便编译器可以将未捕获(已检查)的异常报告为错误。

  2. 它告诉程序员正在编写调用该方法的代码,以期望有什么异常。为此,它经常使感官在 throws 列表中包含未经检查的异常。

注意:生成 API 文档时,javadoc 工具也使用 throws 列表,并通过典型的 IDE悬停文本方法提示。

抛出和方法重写

throws 子句构成方法签名的一部分,用于方法重写。可以使用与重写方法或子集抛出的相同的已检查异常集声明覆盖方法。但是,覆盖方法无法添加额外的已检查异常。例如:

@Override
public void checkEven(int number) throws NullPointerException // OK—NullPointerException is an unchecked exception
    ...

@Override
public void checkEven(Double number) throws OddNumberException // OK—identical to the superclass
    ...

class PrimeNumberException extends OddNumberException {}
class NonEvenNumberException extends OddNumberException {}

@Override
public void checkEven(int number) throws PrimeNumberException, NonEvenNumberException // OK—these are both subclasses

@Override
public void checkEven(Double number) throws IOExcepion         // ERROR

这个规则的原因是,如果一个 overriden 方法可以抛出一个被覆盖的方法无法抛出的已检查异常,那么这将破坏类型的可替代性。