8

I was reading through a Java textbook in a chapter on exceptions and assertions, and came across this block of code that I had a question on.

public boolean searchFor(String file, String word)
    throws StreamException
{
    Stream input = null;

    try {
        input = new Stream(file);
        while (!input.eof())
            if (input.next().equals(word))
                return true;
        return false;         //not found
    } finally {
        if (input != null)
            input.close();
    }
}

In the next paragraph, the text says that "the searchFor method declares that it throws StreamException so that any exceptions generated are passed through to the invoking code after cleanup, including any StreamException thrown by the invocation of close.

I was under the impression that including a throws clause was what allowed a programmer to throw a specific class (or subclass) of an exception, and that a class could be thrown if and only if it or one of its superclasses was in the throws clause. But here, there is a throws clause with no throw statement in the try block. So what is the point of including the clause in the first place? And where in the code would a StreamException be caught?

UnworthyToast
  • 825
  • 5
  • 11
  • 21
  • 2
    if it does throw the exception the finally block will get executed still. Exception will be thrown from the method. – WalterM Nov 27 '15 at 19:26
  • @WalterM but I thought the point of including an exception in a throws clause was so that the compiler would allow you to have specific catch statements with references to the different kinds of exceptions that can be thrown. If a checked exception can be thrown without a catch statement, then what's the point of having a catch statement at all? – UnworthyToast Nov 27 '15 at 19:28
  • Possible duplicate of [Java Try Catch Finally blocks without Catch](http://stackoverflow.com/questions/4559661/java-try-catch-finally-blocks-without-catch) – Raedwald Jan 22 '16 at 15:11

6 Answers6

8

And where in the code would a StreamException be caught?

The try has a finally but no catch. The finally would execute, and the Exception would propagate to the caller.

Elliott Frisch
  • 198,278
  • 20
  • 158
  • 249
  • Ah! Yes I think I was forgetting that an exception will keep searching outward for a catch statement that matches its type if there isn't one found in the first block. Now it makes more sense. Thank you! – UnworthyToast Nov 27 '15 at 19:31
  • 4
    As pointed out by Nathan's [answer](http://stackoverflow.com/a/33963739/2970947), the [`try-with-resources` Statement](http://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html) has an additional advantage in not masking any `Exception` in the `finally` block (I would assume your book predates the `try-with-resources`). – Elliott Frisch Nov 27 '15 at 19:39
  • I'm reading The Java Programming Language, Fourth Edition. All I see in the index are `try-catch`, `try-catch-finally`, and `try-finally`. So yes it must have predated the `try-with-resources` statement. I'll read up on that. – UnworthyToast Nov 27 '15 at 19:42
5

The point is to make sure the stream gets closed, regardless of what else happens in the method. Anything thrown while iterating through the stream gets thrown to the caller. (Each caller in turn is free to either catch the exception or throw it to its caller, and so on.)

If this code used try-with-resources then that would make sure the exception thrown on close couldn't mask the exception thrown while iterating through the stream. (As it is if the close method throws an exception then that's what the caller sees, even if something in the try-block had thrown something.)

Nathan Hughes
  • 94,330
  • 19
  • 181
  • 276
2

The StreamException if I'm not wrong won't be handled from this class but on the one with a catch (StreamException se) {...} i.e. the caller.

The finally block will always be executed no matter if an exception is thrown or not, so it will always close the stream.

You can have 3 different types of try blocks:

  1. try-catch (Try or catch blocks will be executed)
  2. try-catch-finally (Try or catch blocks will be executed AND finally block will execute no matter what)
  3. try-finally (Both blocks will be executed)
Frakcool
  • 10,915
  • 9
  • 50
  • 89
1

Please note that if there isn't a catch, the exception will still escape the block:

try {
    try {
        System.out.println('0');
        int i = 100 / 0; // throw an exception
    } finally {
        System.out.println('1');
    }
    System.out.println('2');
} catch (Exception e) {
    System.out.println('3');
}

Output: 0 1 3

Steven Chou
  • 1,504
  • 2
  • 21
  • 43
0

throws SomeException written followed by method signature,

means some code which is written in side that method-block might be throw compile-time exception.

And as per java's exception rules. while any compile-time exception throws then it needs to be either declare or handle.

Here, in your code not written any throw statement, but some method call from block need to handle or declare it.

throws Exception would propagate to the invoker.
Vishal Gajera
  • 4,137
  • 5
  • 28
  • 55
0

Java 7 introduced the try-with-resources statement that handles this situation perfectly.

public boolean searchFor(String file, String word)
    throws StreamException
{
    try (Stream input = new Stream(file)) {
        while (!input.eof()) {
            if (input.next().equals(word)) {
                return true;
            }
        }
        return false;         //not found
    }
}

This does the same thing as your example, and works for anything that implements AutoCloseable.

Note for anyone replacing code: There is a small difference in which Exception is returned vs suppressed if an exception is thrown in both the try block and the try-with statement or finally block. See Oracle docs for more detail.

hubatish
  • 5,070
  • 6
  • 35
  • 47