10

Historically I have always written my Exception handling code like this:

    Cursor cursor = null;
    try {
        cursor = db.openCursor(null, null);
        // do stuff
    } finally {
        if (cursor != null) cursor.close();
    }

But recently, for reasons of readability and laziness, I have started to do this:

        Cursor cursor = db.openCursor(null, null);
        try {           
            // do stuff
        } finally {
            cursor.close();
        }

Am I wrong to have the assignment to cursor (jdbc handle, whatever) out of the try-catch-finally block?

Barring the JVM actually blowing up on the assignment, or inbetween the assignment and the first line of whatever is in the try block I'm not sure if my old style was lending any extra value, and the second is certainly more readable and concise. The literature generally always does go with the first style though.

EDIT - assume I'm happy for any exceptions thrown by openCursor while initialising the cursor not to be caught in this block of code, my only concern for this example is closing the cursor if it is assigned & opened. Also assume I'm testing for nulls etc.. etc.. yadda... yadda... (I have changed the example to reflect this, it wasn't the focus of my question so I didn't include it in the first version)

Joel
  • 29,538
  • 35
  • 110
  • 138
  • ++ for Mark, sylvarking, jdmichal & PSpeed. I marked PSpeed's correct just on the basis of the comment about leaking cursors, and it had fewest up votes at the time, but ultimately all answers were helpful. StackOverflow - multiple correct answers required!? – Joel Dec 16 '09 at 08:29

8 Answers8

13

I always do mine the second way, because it allows for me to set cursor as final. There's no reason I can see to have the assignment in the try clause if you are not actually trying to catch exceptions from it.

EDIT: Just to note, from the further discussion that has gone on. This is how I would handle the openCursor call throwing an exception:

try
{
    // ALLOCATE RESOURCE
    final Cursor cursor = db.openCursor(null, null);

    try
    {
        // USE RESOURCE
    }
    finally
    {
        // DISPOSE RESOURCE
        cursor.close();
    }
}
catch(OpenCursorException e)
{
    // Handle this appropriately.
}

Note the clean separation of allocation, usage, and disposal. The only time this gets a little interesting is if the usage try block throws the same exception that you're catching for the allocation try block. (IOException would be a particularly good example of this, as opening and reading can both throw one.) In that case, everything will still clean and dispose correctly, but you might incorrectly attribute failure to an initialization exception instead of a usage exception. In this case, you will want to catch the exception(s) in the inner try block and handle them immediately in there.

jdmichal
  • 10,984
  • 4
  • 43
  • 42
11

(Update: the question was corrected based on this answer, so the first part of this answer no longer makes sense.)

The first example is wrong. It will throw a NullPointerException if db.openCursor fails. The second is better.

By the way, I often see the first method done like this:

Cursor cursor = null;
try {
    cursor = db.openCursor(null, null);
    // do stuff
} finally {
    if (cursor != null) {
        cursor.close();
    }
}

It isn't more safe doing this that doing it your second way though, but it is often used in examples and I've seen it used a lot in real code.

One reason why the second method is better is that a bug in the code in the // do stuff section can set the Cursor to null, causing the cursor to not be closed and creating a leak. All in all I can see no good reasons to use the first method (even when it is corrected with the null check), and reasons to avoid using it. Stick to the second method.

(Thanks to PSpeed for the useful comments!)

Mark Byers
  • 811,555
  • 193
  • 1,581
  • 1,452
  • 1
    You should use braces in that if also. – OscarRyz Dec 15 '09 at 19:18
  • Agreed about the NPE, but I believe opening the cursor can throw an exception if too many are open (I couldn't quickly find it in the docs to confirm). Your code here is probably best. – cflewis Dec 15 '09 at 19:18
  • 1
    If openCursor() throws an exception then cursor will always be null. In the code as written there is no good reason to put it in the block and several good reasons not to. – PSpeed Dec 15 '09 at 19:33
  • 4
    For example, if something screwy in // do stuff nulls out the cursor variable then you are now silently leaking cursors where you would have gotten an NPE before. Unnecessary risk. – PSpeed Dec 15 '09 at 19:35
  • 1
    PSpeed: good point. That's definitely one concrete reason to prefer the second method. – Mark Byers Dec 15 '09 at 19:37
  • PSpeed: I merged your comment into the answer. – Mark Byers Dec 15 '09 at 19:42
  • 1
    +1. With second form, you separate resource acquisition, resource use and resource disposal. Although `openCursor` can throw an exception, in most cases these exceptions are not related to the ones that come up from the cursor use. Also as you've noted the `cursor` is always properly disposed. – Alexander Pogrebnyak Dec 15 '09 at 20:10
6

No, you finally got it right.

Don't assign dummy values (null, in this case) to suppress compiler warnings about the use of uninitialized variables. Instead, heed the warning, and initialize your variables properly—as your second, "lazy" example demonstrates.

erickson
  • 265,237
  • 58
  • 395
  • 493
6

If all you are doing in your finally is closing the cursor then the second form is correct. You will never have a cursor to close if openCursor() fails. The value of that variable won't even have been set.

As others allude to, the caveats are if you are doing additional initialization that requires its own clean up then that will logically have to go in the finally{} and change the scope accordingly. Though I'd argue for a restructuring in that case.

The bottom line: as written the first version is needlessly complicated. The second version is correct.

Edit: Incorporating my other comments for posterity...

The first example might seem harmless as all it does is add a bunch of needless code. (Completely needless, if that wasn't clear.) However, in classic "more code means more potential bugs" fashion, there is a hidden gotcha.

If for some reason the "// do something" code inadvertently clears the cursor variable then you will silently leak cursors whereas before you'd at least have gotten a NullPointerException. Since the extra code does absolutely nothing useful, the extra risk is completely unnecessary.

As such, I'm willing to call the first example "just plain wrong". I'd certainly flag it in a code review.

PSpeed
  • 3,346
  • 20
  • 12
  • Note, however, that not checking for null can make it harder to debug the underlying cursor open failure. If an exception is raised during cursor open, the NPE from the finally block will squelch the original exception. – Patrick Linskey Jun 13 '11 at 00:05
  • No... in the second example, if the open fails it throws an exception outside the try/finally block. The only way the cursor can be null in finally is if something really wrong happened inside the try{}... like bad local code wrong. – PSpeed Jun 14 '11 at 07:47
1

There is really nothing wrong in doing :

Cursor cursor = db.openCursor(null, null);  
  try {  
     // do stuff  
   } finally {  
      try {  
        cursor.close();  
     } catch( SomeOther so ){}  
 }  
fastcodejava
  • 39,895
  • 28
  • 133
  • 186
  • 2
    well it would require you to catch (Exception) or (Throwable) or (RuntimeException) in order to catch a possible NPE, all of which should be avoided. – matt b Dec 15 '09 at 20:21
0

If the openCursor() method doesn't throw an exception, the latter is fine. If it does, then you would definitely want to use the former. The reason being that any exception would be thrown to the caller. If the calling method isn't set up to handle that then there is an issue.

user12786
  • 752
  • 3
  • 3
  • But if openCursor() fails then there is no Cursor to close... the cursor variable won't even have a value. – PSpeed Dec 15 '09 at 19:20
0

The second style is fine as long as neither of the method arguments is a calculated expression that can throw its own exception and needs cleaning up after.

ChssPly76
  • 99,456
  • 24
  • 206
  • 195
  • 1
    The first style fails in the same way. Only it appears from your answer that this is less obviously! Second style wins. – Tom Hawtin - tackline Dec 15 '09 at 20:41
  • @Tom - sorry, I didn't quite understand what you meant by that comment. My point was that you don't want to use 2nd style if one (or more) of the arguments (which are `null` in OP's example) is itself a result of function call that can fail. – ChssPly76 Dec 15 '09 at 20:52
0

Different people have different opinions.But It is recommended to use first option because if there is any trouble opening the cursor, an exception could be thrown and handled.That is one safe way of programming.

hari
  • 1,297
  • 5
  • 17
  • 36