Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a preference for nested try/catch blocks?

Tags:

java

try-catch

One of the things that always bugs me about using Readers and Streams in Java is that the close() method can throw an exception. Since it's a good idea to put the close method in a finally block, that necessitates a bit of an awkward situation. I usually use this construction:

FileReader fr = new FileReader("SomeFile.txt"); try {     try {         fr.read();     } finally {         fr.close();     } } catch(Exception e) {     // Do exception handling } 

But I've also seen this construction:

FileReader fr = new FileReader("SomeFile.txt"); try {     fr.read()  } catch (Exception e) {     // Do exception handling } finally {     try {         fr.close();     } catch (Exception e) {         // Do exception handling     } } 

I prefer the first construction because there's only one catch block and it just seems more elegant. Is there a reason to actually prefer the second or an alternate construction?

UPDATE: Would it make a difference if I pointed out that both read and close only throw IOExceptions? So it seems likely to me that, if read fails, close will fail for the same reason.

like image 333
eaolson Avatar asked Oct 08 '08 15:10

eaolson


People also ask

Is it good to have nested try catch?

Nesting try-catch blocks severely impacts the readability of source code because it makes it to difficult to understand which block will catch which exception.

Can try catch blocks be nested?

Yes, we can declare a try-catch block within another try-catch block, this is called nested try-catch block.

Why should I not wrap every block in try catch?

Exponentially because if each method branches in two different ways then every time you call another method you're squaring the previous number of potential outcomes. By the time you've called five methods you are up to 256 possible outcomes at a minimum.

Are multiple catch blocks mandatory for each try block?

Yes, we can define one try block with multiple catch blocks in Java. Every try should and must be associated with at least one catch block.


2 Answers

I'm afraid there's a big problem with the first example, which is that if an exception happens on or after the read, the finally block executes. So far so good. But what if the fr.close() then causes another exception to be thrown? This will "trump" the first exception (a bit like putting return in a finally block) and you will lose all information about what actually caused the problem to begin with.

Your finally block should use:

IOUtil.closeSilently(fr); 

where this utility method just does:

public static void closeSilently(Closeable c) {     try { c.close(); } catch (Exception e) {}  }  
like image 58
oxbow_lakes Avatar answered Sep 19 '22 07:09

oxbow_lakes


I would always go for the first example.

If close were to throw an exception (in practice that will never happen for a FileReader), wouldn't the standard way of handling that be to throw an exception appropriate to the caller? The close exception almost certainly trumps any problem you had using the resource. The second method is probably more appropriate if your idea of exception handling is to call System.err.println.

There is an issue of how far exceptions should be thrown. ThreadDeath should always be rethrown, but any exception within finally would stop that. Similarly Error should throw further than RuntimeException and RuntimeException further than checked exceptions. If you really wanted to you could write code to follow these rules, and then abstract it with the "execute around" idiom.

like image 44
Tom Hawtin - tackline Avatar answered Sep 19 '22 07:09

Tom Hawtin - tackline