Difference between Throws in method signature and Throw Statements in Java

Weishi Z picture Weishi Z · Oct 5, 2013 · Viewed 35.3k times · Source

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();
}

Answer

Vidya picture Vidya · Oct 5, 2013

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.