一尘不染

Java中方法签名中的Throw和Throw语句之间的区别

java

我试图弄清楚 方法签名中的 Throw 和Java中的 Throw语句 之间的区别。方法签名的抛出如下:

public void aMethod() throws IOException{
    FileReader f = new FileReader("notExist.txt");
}

抛出语句如下:

public void bMethod() {
    throw new IOException();
}

据我了解,throws方法内签名是一种通知,通知该方法可能会抛出此类异常。throw语句是根据情况实际抛出创建的对象的东西。从这个意义上说,如果方法中存在
throw* 语句,则应始终出现 throw in方法签名。 *

但是,以下代码似乎没有这样做。代码来自库。我的问题是为什么会这样?我是否理解错误的概念?

这段代码是java.util.linkedList的副本。@作者Josh Bloch

 /**
 * Returns the first element in this list.
 *
 * @return the first element in this list
 * @throws NoSuchElementException if this list is empty
 */
public E getFirst() {
    final Node<E> f = first;
    if (f == null)
        throw new NoSuchElementException();
    return f.item;
}

更新答案:

更新1:上面的代码是否与以下代码相同?

// as far as I know, it is the same as without throws
public E getFirst() throws NoSuchElementException {
    final Node<E> f = first;
    if (f == null)
        throw new NoSuchElementException();
    return f.item;
}

更新2:用于检查的异常。签名中是否需要“投掷”?是。

// has to throw checked exception otherwise compile error
public String abc() throws IOException{
    throw new IOException();
}

阅读 330

收藏
2020-12-03

共1个答案

一尘不染

您几乎是正确的。除了一件事,我会稍作提及。

throws 和名称和参数一样,也是方法API的一部分。客户知道他们是否调用该方法,他们需要处理该异常-
通过简单地将其抛出或捕获并处理它(实际上可能需要引发另一个包装原始异常的异常)。 抛出 是在编译时解决的。

throw 是让运行时知道发生了什么不好的事情的实际行为-实际上,我们担心的异常情况已经发生。因此,它需要在运行时处理。

但是当您说“如果方法中存在throw语句时,应该总是出现方法签名中的throws”,您就不太对劲。这通常是正确的,但并非总是如此。我还可以调用另一个在我的方法中引发异常的方法,如果我没有捕获到该异常,则我的方法需要抛出该异常。在那种情况下,我没有明确抛出相同的异常。

最后一点是,仅当异常是已 检查的 异常时才需要在 throws中 声明一个异常-
这意味着它来自RuntimeException的Exception类层次结构的另一侧。常见的检查异常是IOException和SQLException。如果您自己不处理,则必须在方法签名的throws部分中列出已检查的异常。子类RuntimeException的任何子类(如示例中的NoSuchElementException以及讨厌的NullPointerException子类)都是未经检查的异常,无需捕获或抛出。
__

通常,对于可恢复的问题(客户端知道发生了什么并且可以妥善处理问题并继续进行),您可以使用检查异常,而对于灾难性问题(例如无法连接至数据库)则使用检查异常。

如果您可以克服所有AOP问题,那么这将是关于如何有效使用检查和未检查异常的很好的讨论。

2020-12-03