Is a finally block without a catch block java anti-pattern?

I had a rather painful troubleshooting experience finding and fixing some errors that looked like this:

try { doSomeStuff() doMore() } finally { doSomeOtherStuff() } 

The problem was difficult to troubleshoot because doSomeStuff () threw an exception, which in turn threw doSomeOtherStuff () to throw an exception as well. The second exception (thrown by the finally block) was passed to my code, but it did not have the handle of the first exception (selected from doSomeStuff ()), which was the main cause of the problem.

If this code said this, the problem would be obvious:

 try { doSomeStuff() doMore() } catch (Exception e) { log.error(e); } finally { doSomeOtherStuff() } 

So my question is this:

Is the finally block used by a non-blocking catch java anti-pattern known? (This, of course, does not seem to be a completely understandable subclass of the obviously well-known anti-pattern "Don't catch exceptions!")

+43
java c ++ c # exception try-catch-finally
Mar 02 '09 at 3:08
source share
12 answers

In general, no, this is not an anti-pattern. The point of finally blocks is to make sure that the material is cleared of whether an exception is thrown or not. The whole point of exception handling is that if you can't handle it, you let it bubble up to those who can, thanks to the relatively clean out-of-band signaling exception handling. If you need to make sure that the material is cleared if an exception is thrown, but cannot correctly handle the exception in the current area, then this is exactly what needs to be done. You might want to take a little care to make sure your finally block is not thrown.

+61
Mar 02 '09 at 3:14
source share

I think the real "anti-pattern" here is doing something in the finally block, which it can throw without having a trick.

+26
Mar 02 '09 at 3:19
source share

Not at all.

What is the code error inside.

Remember that in the end, you will always be fulfilled and it’s just risky (as you just witnessed) to put something that could throw an exception there.

+16
Mar 02 '09 at 4:15
source share

There is absolutely nothing wrong with trying with an ending and without a catch. Consider the following:

 InputStream in = null; try { in = new FileInputStream("file.txt"); // Do something that causes an IOException to be thrown } finally { if (in != null) { try { in.close(); } catch (IOException e) { // Nothing we can do. } } } 

If an exception is thrown and this code does not know how to deal with it, then the exception should call the call stack for the caller. In this case, we still want to clear the stream, so I think it makes sense to have a try block without catch.

+10
Mar 02 '09 at 3:15
source share

I think that this is far from an anti-pattern, and this is what I do very often when it critically frees resources received during the execution of a method.

One thing I do when working with file descriptors (for writing) is to clear the stream before closing it using the IOUtils.closeQuietly method, which does not throw exceptions:

 OutputStream os = null; OutputStreamWriter wos = null; try { os = new FileOutputStream(...); wos = new OutputStreamWriter(os); // Lots of code wos.flush(); os.flush(); finally { IOUtils.closeQuietly(wos); IOUtils.closeQuietly(os); }
OutputStream os = null; OutputStreamWriter wos = null; try { os = new FileOutputStream(...); wos = new OutputStreamWriter(os); // Lots of code wos.flush(); os.flush(); finally { IOUtils.closeQuietly(wos); IOUtils.closeQuietly(os); } 

I like to do this for the following reasons:

  • You cannot completely ignore the exception when closing the file - if there are still bytes that have not yet been written to the file, then the file may not be in the state that the waiting one would call;
  • So, if an exception occurs during the flush () method, it will be passed to the caller, but I will still make all files private. The IOUtils.closeQuietly (...) method is less detailed, then the corresponding try ... catch ... ignore me block;
  • When using multiple output streams, order for the flush () method is very important. Threads created by passing other threads as constructors must be flushed first. The same is true for the close () method, but flush () is more clear in my opinion.
+5
Mar 02 '09 at 5:23
source share

I am using try / finally in the following form:

 try{ Connection connection = ConnectionManager.openConnection(); try{ //work with the connection; }finally{ if(connection != null){ connection.close(); } } }catch(ConnectionException connectionException){ //handle connection exception; } 

I prefer this for try / catch / finally (+ the nested try / catch in finally). I think it is more concise and I do not duplicate catch (Exception).

+1
Mar 02 '09 at 3:40
source share
 try { doSomeStuff() doMore() } catch (Exception e) { log.error(e); } finally { doSomeOtherStuff() } 

Don’t do this ... you just hid more errors (well, you didn’t quite hide them ... but you couldn’t figure it out. When you catch an Exception, you will also catch any RuntimeException (for example, NullPointer and ArrayIndexOutOfBounds).

In general, catch the exceptions you need to catch (checked exceptions) and communicate with others during testing. RuntimeExceptions are intended to be used for programmer errors, and programmer errors are things that should not be executed in a properly debugged program.

+1
Mar 02 '09 at 3:40
source share

In my opinion, this is more likely the case when finally with a catch indicates some kind of problem. The resource idiom is very simple:

 acquire try { use } finally { release } 

In Java, you can have an exception from almost anywhere. Often the acquirer throws a proven exception, a sensible way to handle this is to catch around how much. Do not try to eliminate the null check.

If you were really anal, you should note that among the exceptions there are certain priorities. For example, ThreadDeath should compress everything, regardless of whether it comes from receiving / using / releasing. Proper management of these priorities is unsightly.

Therefore, abstract the processing of your resources with the Execute Around idiom.

+1
Mar 02 '09 at 12:49
source share

I would say that a try block without a catch block is an anti-pattern. The statement “Don't have a catch without catch” is a subset of “Don't try without a catch.”

0
Mar 02 '09 at 3:14
source share

Try / Finally, this is a way to free resources properly. The code in the finally block should never be thrown, because it should only act on the resources or the state that PRIOR received to enter the try block.

Aside, I think log4J is almost an anti-pattern.

IF YOU WANT TO CHECK THE WORK PROGRAM USE INSTRUCTIONS INSPECTION INSTRUCTIONS (that is, a debugger, IDE or in the extreme sense - a byte code encoder, but DO NOT START MESSAGES IN EVERY SEVERAL LINE!).

In the two examples that you present, the first one looks correct. The second is the registrar code and introduces an error. In the second example, you suppress the exception if you throw the first two statements (i.e. you break it and register, but don't revert). This is what I find very common in using log4j and represents a real application development problem. with your change, you refuse the program in such a way that the system is processed very hard, since you basically march forward, as if you never had an exception (it seems like VB basic will resume the next construct if it fails).

0
Oct 12 '09 at 4:44
source share

try-finally can help you reduce copy-paste code if the method has multiple return . Consider the following example (Android Java):

 boolean doSomethingIfTableNotEmpty(SQLiteDatabase db) { Cursor cursor = db.rawQuery("SELECT * FROM table", null); if (cursor != null) { try { if (cursor.getCount() == 0) { return false; } } finally { // this will get executed even if return was executed above cursor.close(); } } // database had rows, so do something... return true; } 

If there was no finally clause, you might need to write cursor.close() twice: before return false , and also after the surrounding if clause.

0
Apr 15 '14 at 10:39
source share

I think trying without a catch is an anti-pattern. Using try / catch to handle exceptional conditions (file I / O errors, socket timeout, etc.) is not an anti-pattern.

If you use try / finally for cleaning, consider using a block instead.

-one
Mar 02 '09 at 3:51
source share



All Articles