我试图弄清楚 方法签名中的 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方法签名。 *
throws
throw
但是,以下代码似乎没有这样做。代码来自库。我的问题是为什么会这样?我是否理解错误的概念?
这段代码是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(); }
您几乎是正确的。除了一件事,我会稍作提及。
throws 和名称和参数一样,也是方法API的一部分。客户知道他们是否调用该方法,他们需要处理该异常- 通过简单地将其抛出或捕获并处理它(实际上可能需要引发另一个包装原始异常的异常)。 抛出 是在编译时解决的。
throw 是让运行时知道发生了什么不好的事情的实际行为-实际上,我们担心的异常情况已经发生。因此,它需要在运行时处理。
但是当您说“如果方法中存在throw语句时,应该总是出现方法签名中的throws”,您就不太对劲。这通常是正确的,但并非总是如此。我还可以调用另一个在我的方法中引发异常的方法,如果我没有捕获到该异常,则我的方法需要抛出该异常。在那种情况下,我没有明确抛出相同的异常。
最后一点是,仅当异常是已 检查的 异常时才需要在 throws中 声明一个异常- 这意味着它来自RuntimeException的Exception类层次结构的另一侧。常见的检查异常是IOException和SQLException。如果您自己不处理,则必须在方法签名的throws部分中列出已检查的异常。子类RuntimeException的任何子类(如示例中的NoSuchElementException以及讨厌的NullPointerException子类)都是未经检查的异常,无需捕获或抛出。 __
通常,对于可恢复的问题(客户端知道发生了什么并且可以妥善处理问题并继续进行),您可以使用检查异常,而对于灾难性问题(例如无法连接至数据库)则使用检查异常。
如果您可以克服所有AOP问题,那么这将是关于如何有效使用检查和未检查异常的很好的讨论。