Developer poll. return within finally: I need your opinons

D

Duncan Strang

Hi

I'd be interested to hear what developers think about the following
issue that has been doing the rounds here at work.

Say we have the following code

public int confused(){
String foo = "bar";
int val = -1;
try{
val = Integer.parseInt(foo);
}
catch(Exception ex){
ex.printStackTrace();
}
finally{
System.out.println("This always executes");
return val;
}
}

The question is:

What do you think about inserting a return within a finally block ?

The language spec appears ambiguous, also different versions of the
compiler behave differently, for example.

Compiling the above with j2se 1.4.1_02-b06 gives no warnings.

Compiling with j2se 1.4.2-b28 gives the following warning

Test.java [38:1] warning: finally clause cannot complete normally
}
^
1 warning
Finished Test.

I've read various articles and specs that seem to indicate that the
jvm handles the stack correctly (in terms of return addresses for
example) but the compiler still raises the warning.

All opinions gratefully accepted

Cheers
Duncan L.Strang
 
R

Ryan Stewart

Hi

I'd be interested to hear what developers think about the following
issue that has been doing the rounds here at work.

Say we have the following code

public int confused(){
String foo = "bar";
int val = -1;
try{
val = Integer.parseInt(foo);
}
catch(Exception ex){
ex.printStackTrace();
}
finally{
System.out.println("This always executes");
return val;
}
}

The question is:

What do you think about inserting a return within a finally block ?

The language spec appears ambiguous, also different versions of the
compiler behave differently, for example.

Compiling the above with j2se 1.4.1_02-b06 gives no warnings.

Compiling with j2se 1.4.2-b28 gives the following warning

Test.java [38:1] warning: finally clause cannot complete normally
}
^
1 warning
Finished Test.

I've read various articles and specs that seem to indicate that the
jvm handles the stack correctly (in terms of return addresses for
example) but the compiler still raises the warning.

All opinions gratefully accepted

Cheers
Duncan L.Strang
I'd consider that the least preferable way to do it. Why return from a
finally block when you can get exactly the same result by setting the
variable within the finally and returning *after* it? It could also cause
problems if someone less knowledgable has to maintain this code later on.
Question for you: if you put a return statement in the try block *and* in
the finally block, what happens? If you don't know, why would you expect
someone less experienced to know? And if you do know, same question. The
answer is that the finally block will be executed and that return value will
be used. The return in the try block is basically ignored.
 
D

Duncan Strang

Hi

I'd be interested to hear what developers think about the following
issue that has been doing the rounds here at work.

Say we have the following code

public int confused(){
String foo = "bar";
int val = -1;
try{
val = Integer.parseInt(foo);
}
catch(Exception ex){
ex.printStackTrace();
}
finally{
System.out.println("This always executes");
return val;
}
}

The question is:

What do you think about inserting a return within a finally block ?

The language spec appears ambiguous, also different versions of the
compiler behave differently, for example.

Compiling the above with j2se 1.4.1_02-b06 gives no warnings.

Compiling with j2se 1.4.2-b28 gives the following warning

Test.java [38:1] warning: finally clause cannot complete normally
}
^
1 warning
Finished Test.

I've read various articles and specs that seem to indicate that the
jvm handles the stack correctly (in terms of return addresses for
example) but the compiler still raises the warning.

All opinions gratefully accepted

Cheers
Duncan L.Strang
I'd consider that the least preferable way to do it. Why return from a
finally block when you can get exactly the same result by setting the
variable within the finally and returning *after* it? It could also cause
problems if someone less knowledgable has to maintain this code later on.
Question for you: if you put a return statement in the try block *and* in
the finally block, what happens? If you don't know, why would you expect
someone less experienced to know? And if you do know, same question. The
answer is that the finally block will be executed and that return value will
be used. The return in the try block is basically ignored.

Ryan, calm down, I wasn't suggesting it was the correct way to do
things I was simply asking for opinions ... I guess you are a 'no'
then

Rgds
Duncan
 
M

Manavendra Gupta

I dont think its a good idea to return a value from the finally block, for
several reasons:
+ from what i understand of the spec, you use finally for any resource
free-up (closing any socket or database connections )
+ again, the spec guarantees finally block will be executed, but thats not
the most obvious place other reading your code will look at, to find the
return values.
+ returning a value from the finally block, IMO, gives a false impression
that everything went fine, that there were no exceptions. if you return a
value from a finally block then i'm sure you will be examining the value in
the caller method to see what happened - and you'd have an intrinsic "logic"
that "-1" (in your example), means something went wrong and take an
alternative action. this approach rings a bells of structured programming
days, doesn't it? why not return a value only if everything is alright (from
within the try block), and throw a typed exception if an exceptional
situation occured?

I believe, the key here is to question the very motive of returning a value
from a finally block.
 
C

Chris Uppal

Duncan said:
What do you think about inserting a return within a finally block ?

The language spec appears ambiguous, also different versions of the
compiler behave differently, for example.

I think that it's legal and unambiguous Java. But the warning might be
justified by code like:

public int moreConfused()
{
try
{
return 22;
}
finally
{
return 33;
}
}

which might not be expected to return 33, but it does.

-- chris
 
R

Ryan Stewart

Hi

I'd be interested to hear what developers think about the following
issue that has been doing the rounds here at work.

Say we have the following code

public int confused(){
String foo = "bar";
int val = -1;
try{
val = Integer.parseInt(foo);
}
catch(Exception ex){
ex.printStackTrace();
}
finally{
System.out.println("This always executes");
return val;
}
}

The question is:

What do you think about inserting a return within a finally block ?

The language spec appears ambiguous, also different versions of the
compiler behave differently, for example.

Compiling the above with j2se 1.4.1_02-b06 gives no warnings.

Compiling with j2se 1.4.2-b28 gives the following warning

Test.java [38:1] warning: finally clause cannot complete normally
}
^
1 warning
Finished Test.

I've read various articles and specs that seem to indicate that the
jvm handles the stack correctly (in terms of return addresses for
example) but the compiler still raises the warning.

All opinions gratefully accepted

Cheers
Duncan L.Strang
I'd consider that the least preferable way to do it. Why return from a
finally block when you can get exactly the same result by setting the
variable within the finally and returning *after* it? It could also cause
problems if someone less knowledgable has to maintain this code later on.
Question for you: if you put a return statement in the try block *and* in
the finally block, what happens? If you don't know, why would you expect
someone less experienced to know? And if you do know, same question. The
answer is that the finally block will be executed and that return value will
be used. The return in the try block is basically ignored.

Ryan, calm down, I wasn't suggesting it was the correct way to do
things I was simply asking for opinions ... I guess you are a 'no'
then

Rgds
Duncan

Calm down? I'm fine. And yes, that was a no for the reasons I listed. You
asked for opinions, you got one. I'd consider it acceptable from a logical
point of view. In fact, I was surprised to learn you got a warning from it.
However, the possible cons outweigh the pros considerably, I think.
 
J

John C. Bollinger

Duncan said:
Hi

I'd be interested to hear what developers think about the following
issue that has been doing the rounds here at work.

Say we have the following code

public int confused(){
String foo = "bar";
int val = -1;
try{
val = Integer.parseInt(foo);
}
catch(Exception ex){
ex.printStackTrace();
}
finally{
System.out.println("This always executes");
return val;
}
}

The question is:

What do you think about inserting a return within a finally block ?

The language spec appears ambiguous, also different versions of the
compiler behave differently, for example.

Compiling the above with j2se 1.4.1_02-b06 gives no warnings.

Compiling with j2se 1.4.2-b28 gives the following warning

Test.java [38:1] warning: finally clause cannot complete normally
}
^
1 warning
Finished Test.

I've read various articles and specs that seem to indicate that the
jvm handles the stack correctly (in terms of return addresses for
example) but the compiler still raises the warning.

Section 14.1 of the Language Spec (2nd Ed.) covers normal vs. abrupt
completion of statements in general, section 14.16 discusses all aspects
of the return statement, and section 14.19 discusses all aspects of
try-catch-finally.

Return statements by definition never complete normally, therefore the
compiler warning is valid. Perhaps the question is whether or not it is
useful -- I think it is. As Chris Uppal noted, the behavior of this
construct and similar are well defined. That doesn't mean that their
use is good practice, however. In the first place, implementation bugs
(i.e. compiler / VM bugs in this case) tend to live in little corners
like this, and it's no fun to troubleshoot a failure of your product
that turns out to live in one of those places. More importantly, it is
unwise to write code whose correct interpretation by another human
depends on knowledge of such fine details of the language -- you are
asking for maintenance problems down the road.

The precise construct you provided isn't so bad, but small variations
rapidly become confusing. For instance, what if the try block contains
one or more return statements? Or what if a throwable can go unhandled
by any catch block (e.g. as an OutOfMemoryError would do even in the
sample)? What if the finally block contains statements that might throw
an exception? What if the body of the try statement is long enough that
the presence of a return in the finally block isn't apparent? The
behavior is well defined in all these cases, but its interpretation may
be tricky.

The final nail with respect to the sample code specifically is that the
whole issue can be removed by simply moving the return statement after
the finally block. Behavior would be identical except in the case of a
Throwable other than an Exception being thrown from the try statement,
and arguably you would want to pass something like that on up the call
stack anyway.

Coming back to the compiler warning specifically, I repeat that I think
it useful and appropriate. It is advising you of a dubious programming
practice, hence it is a warning rather than an error. I would heed it.


John Bollinger
(e-mail address removed)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top