1

In the "Chapter 11: Risky Behavior" of the book Head First Java (2nd edition) it's said that "a try without a catch doesn't satisfy the handle or declare law" and gives an example:

void go() throws fooException {
    try {
        x.doStuff();
    } finally {
        //something
    }
}

But can't this code be interpreted as a "ducking", given that it throws the exception to whichever method calling it without handling the problem?

Erwin Bolwidt
  • 30,799
  • 15
  • 56
  • 79
  • 2
    I'm not sure exactly what you mean, but it's certainly a legitimate thing to do and not a "well it's someone else's problem now" sort of thing. If there's something that must be done here, even in the case of failure, then it belongs in a finally block. If failures can't be dealt with here, then calling methods should know about those failures. – user1675642 Jan 22 '16 at 14:58
  • 1
    What is this "handle or declare law". No other SO questions mention it. – Raedwald Jan 22 '16 at 15:02
  • See http://stackoverflow.com/questions/4559661/java-try-catch-finally-blocks-without-catch – Raedwald Jan 22 '16 at 15:06

3 Answers3

0

In general, if you're expecting an exception to be thrown, and you don't intend to catch and handle it yourself, it's polite to warn other programmers that your method is expected to throw the exception. If an exception bubbles up without having been declared, whoever called the exploding method will be astonished when their application suddenly fails. Finding ways around this choice is considered bad practice.

That being said, I've pretty much never seen try/finally in practice. A more common programmming mistake is the empty catch block, in which an exception is caught and silently thrown away. While a try/finally block would manifest itself blatantly and be quickly caught in testing, the empty catch block creates more subtle bugs because the program doesn't inform anyone that it is breaking.

Jim W
  • 492
  • 2
  • 11
0

Looking at the Head First Java book (specifically the section "Ducking (by declaring) only delays the inevitable"), your sample meets their definition of "ducking," but that doesn't mean there's a problem. The only issue they point out is where every nested method call propagates an exception, including the main method, so that the JVM has to handle it. Even then, if you have a headless batch job where you want some exceptions to terminate the job (and you might have it logged by calling the java code from a shell script that redirects stderr to a file so exceptions get logged), this might be fine, it depends on what you need to do. It is just something to be aware of.

The whole point of exceptions is that when you run into a problem a lot of the time that place in the code is not the place to address that problem, instead you need to relocate control to another spot higher up in the call stack. In many cases the best policy is to create a global exception handler that takes in exceptions thrown from many different levels in the application (for instance, in a web application, where if there's an error in many cases the best thing to do is terminate the request, log the exception, and present an error page).

Handling an exception immediately where it's first thrown is really relatively unusual. There is nothing wrong with having a method pass on catching an exception, letting it be thrown from the method. The book is only trying to point out that eventually something should catch it.

There is a possible problem with finally blocks to be aware of. Say something goes wrong in your doStuff method that causes an exception to be thrown. On the way out the finally block gets called, and if anything is thrown from the finally block, then that exception takes precedence and the exception thrown from the try block gets lost. This is called exception masking. It's bad because usually the exception thrown by the finally is not the one you want to see, the one thrown by the try-block is the informative one. The try-with-resources statement was created to help deal with this problem by suppressing the exception thrown on close when another exception was being thrown from the try block.

Nathan Hughes
  • 94,330
  • 19
  • 181
  • 276
-1

You either do a try/catch block or add a throws, not a hybrid of the two.

void go() throws fooException { /* do something */ }

Or

void go() { try {} catch(FooException e) {} finally { /* do something */ }}
Erwin Bolwidt
  • 30,799
  • 15
  • 56
  • 79
  • 1
    There's actually a good reason to have a try-finally without a catch in a method that throws an exception, which is that even though you can't handle the exception, you still might need to react to it being thrown, e.g. `try { stuff } finally { clean up stuff }`. – azurefrog Jan 22 '16 at 14:58