I am trying to make it clear of the difference between Throws in method signature and Throw Statements in Java.
Throws in method signature is as following:
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, throws in method signature should always appear if there exist a throw statement in the method.
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
/**
* 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?
// 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.
// has to throw checked exception otherwise compile error
public String abc() throws IOException{
throw new IOException();
}
You are pretty much right on. Except for one thing I'll mention in a bit.
throws is 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). throws is addressed at compile time.
throw is 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.
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.
The final point is that you only need to declare an exception in throws when the exception is a checked exception--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.
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, this is a great discussion of how you use checked and unchecked exceptions effectively.
Vidya provided great answer to your questions.
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"
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:
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 IOException and something bad happens inside finally{} statement - it would cause an error.
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 exception is something that the caller MUST always 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.
On the other hand other exceptions, namely unchecked or runtime exceptions, (NoSucheElementException
is one example) are exceptions which you are not forced to specify becuase they arise from different situations.
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
)
RuntimeException
s dont have to be handled in try-catch block so they dont have to be declared as thrown and NoSuchElementException is RuntimeException
because it extends it.