Java 中方法签名中的抛出和抛出语句的区别
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19193540/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Difference between Throws in method signature and Throw Statements in Java
提问by Weishi Zeng
I am trying to make it clear of the difference between Throws in method signatureand Throw Statementsin Java. Throws in method signature is as following:
我试图弄清楚方法签名中的 Throws和Java 中的Throw Statements之间的区别。抛出方法签名如下:
public void aMethod() throws IOException{
FileReader f = new FileReader("notExist.txt");
}
Throw Statements is as following:
抛出语句如下:
public void bMethod() {
throw new IOException();
}
From my understanding, a throws
in method signature is a notification that the method may throw such an exception. throw
statement is what actually throw a created object under according circumstances.
In that sense, throwsin method signature should always appear if there exist a throwstatement in the method.
根据我的理解,一个throws
in 方法签名是一个通知,该方法可能会抛出这样的异常。throw
语句是根据情况实际抛出创建的对象的内容。从这个意义上说,如果方法中存在throw语句,则方法签名中的throws应该始终出现。
However, the following code doesn't seem doing so. The code is from the library. My question is why it is happening? Am I understanding the concepts wrong?
但是,以下代码似乎没有这样做。代码来自图书馆。我的问题是为什么会这样?我对这些概念的理解有误吗?
This piece of code is a copy from java.util.linkedList. @author Josh Bloch
这段代码是从 java.util.linkedList 复制的。@作者乔什·布洛赫
/**
* 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;
}
Update on the answer:
更新答案:
update 1 : is above code the same as the following?
更新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;
}
update 2 : For checked exception. Do I need to have "throws" in the signature? Yes.
更新 2 :对于检查异常。我需要在签名中有“抛出”吗?是的。
// has to throw checked exception otherwise compile error
public String abc() throws IOException{
throw new IOException();
}
采纳答案by Vidya
You are pretty much right on. Except for one thing I'll mention in a bit.
你说得很对。除了我稍后会提到的一件事。
throwsis as much a part of the method API as the name and the parameters. Clients know if they call that method, they need to handle that exception--by simply throwing it also or by catching it and handling it (which may in fact entail the throwing of another exception wrapping the original). throwsis addressed at compile time.
throws与名称和参数一样是方法 API 的一部分。客户知道如果他们调用该方法,他们需要处理该异常——通过简单地也抛出它或通过捕获它并处理它(这实际上可能需要抛出另一个包含原始异常的异常)。throws在编译时被解决。
throwis the actual act of letting the runtime know something bad happened--that the exceptional condition we were worried about has in fact taken place. So it needs to be dealt with at runtime.
throw是让运行时知道发生了不好的事情的实际行为——我们担心的异常情况实际上已经发生了。所以需要在运行时进行处理。
But you weren't quite right when you said, "Throws in method signature should always appear if there exist a throw statement in the method." That is often true but not always. I could also call another method that throws an exception within my method, and if I don't catch it, my method needs to throw it. In that case, there is no explicit throw of the same exception by me.
但是你说的不太对,“如果方法中存在 throw 语句,则方法签名中的抛出应该总是出现”。这通常是正确的,但并非总是如此。我也可以调用另一个在我的方法中抛出异常的方法,如果我没有捕捉到它,我的方法需要抛出它。在那种情况下,我没有明确抛出相同的异常。
The final point is that you only need to declare an exception in throwswhen the exception is a checkedexception--meaning it is from the other side of the Exception class hierarchy from RuntimeException. Common checked exceptions are IOException and SQLException. Checked exceptions must be listed in the throws part of the method signature if you don't handle them yourself. Anything subclassing RuntimeException--like NoSuchElementException in your example and also the hated NullPointerException--is an unchecked exception and doesn't have to be caught or thrown or anything.
最后一点是,当异常是已检查异常时,您只需要在throws 中声明异常——这意味着它来自 RuntimeException 的 Exception 类层次结构的另一端。常见的检查异常是 IOException 和 SQLException。如果您不自己处理已检查的异常,则必须在方法签名的 throws 部分列出它们。任何继承 RuntimeException 的东西——比如你的例子中的 NoSuchElementException 以及讨厌的 NullPointerException——都是未经检查的异常,不必被捕获或抛出或任何东西。
Typically, you use checked exceptions for recoverable problems (where the client knows what can happen and can gracefully handle the problem and move on) and unchecked exceptions for catastrophic problems (like can't connect to the database).
通常,对于可恢复的问题(客户端知道会发生什么并且可以优雅地处理问题并继续前进)和未检查异常对于灾难性问题(例如无法连接到数据库)使用检查异常。
If you can get past all the AOP stuff, thisis a great discussion of how you use checked and unchecked exceptions effectively.
如果你能通过所有 AOP 的东西,这是一个关于如何有效地使用检查和未检查异常的很好的讨论。
回答by Pshemo
RuntimeException
s dont have to be handled in try-catch block so they dont have to be declared as thrown and NoSuchElementExceptionis RuntimeException
because it extends it.
RuntimeException
s 不必在 try-catch 块中处理,因此不必将它们声明为抛出,而NoSuchElementException是RuntimeException
因为它扩展了它。
回答by Hyman
throw
attribute in method signature, like you correctly guessed, is a hint to the compiler that the method raises an exception that must be caught by the caller. This kind of exception, namely called checked exceptionis something that the caller MUSTalways catch or dispatch to its caller again. This is something at compiler level, the signature specifies which exception the method is able to throw: this enforces a try-catch
or re-dispatch in the caller and a throw statement somewhere inside the method, is a constraint that the developer places to specify something about the method behavior.
throw
方法签名中的属性,就像您正确猜到的那样,是对编译器的一个提示,即该方法引发了一个必须由调用者捕获的异常。这种异常,即所谓的检查异常是调用者必须总是再次捕获或调度给其调用者的异常。这是编译器级别的东西,签名指定了该方法能够抛出的异常:这try-catch
在调用者中强制执行 a or re-dispatch 和方法内部某处的 throw 语句,是开发人员用来指定有关方法行为。
On the other hand other exceptions, namely uncheckedor runtime exceptions, (NoSucheElementException
is one example) are exceptions which you are not forced to specify becuase they arise from different situations.
另一方面,其他异常,即未经检查或运行时异常(NoSucheElementException
是一个示例)是您不必指定的异常,因为它们来自不同的情况。
The conceptual difference is that checked exception are usually used to warn about exceptional situation which should be handled somehow (think about IOException
) by the developer, while unchecked are real errors (like NullPointerException
or like in your example NoSuchElementException
)
概念上的区别在于,已检查异常通常用于警告IOException
开发人员应以某种方式处理(考虑)的异常情况,而未检查是真正的错误(例如NullPointerException
或像您的示例中那样NoSuchElementException
)
回答by 0leg
Vidya provided great answer to your questions.
Vidya 很好地回答了您的问题。
The most important words are "The final point is that you only need to declare an exception in throws when the exception is a checked exception"
最重要的话是“最后一点是,当异常是已检查异常时,您只需要在throws中声明异常”
Just to show you an example code what does this mean. Imagine that we would like to use FileOutputStream in order to pass some data. The function would look like this:
只是为了向您展示示例代码,这是什么意思。想象一下,我们想使用 FileOutputStream 来传递一些数据。该函数如下所示:
public void saveSomeData() throws IOException {
FileInputStream in = null;
FileOutputStream out = null;
try {
in = new FileInputStream("input.txt");
out = new FileOutputStream("output.txt");
int c;
while ((c = out.read() != -1) {
in.write(c);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
// Close in
if (in != null) {
in.close(); // <-- If something bad happens here it will cause runtime error!
}
// Close out
...
}
}
Now imagine, if you wouldn't provide throws IOExceptionand something bad happens inside finally{} statement - it would cause an error.
现在想象一下,如果您不提供throws IOException并且在 finally{} 语句中发生一些不好的事情 - 它会导致错误。