File APIs for Java Developers
Manipulate DOC, XLS, PPT, PDF and many others from your application.
http://aspose.com/file-tools
Win a copy of Clojure in Action this week in the Clojure forum!
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

Finally return causing unreachable statements

 
Ruben Soto
Ranch Hand
Posts: 1032
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Does anybody know why javac allows this code to compile, even when the return statements in the try and catch blocks are unreachable?


In contrast, if you have something like this:

The compiler complains that // Unreachable is unreachable.

Thanks!
 
Jelle Klap
Bartender
Posts: 1951
7
Eclipse IDE Java
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Because section 14.20.2 of the JLS says so (third edition):


If execution of the try block completes abruptly for any other reason R, then the finally block is executed. Then there is a choice:
If the finally block completes normally, then the try statement completes abruptly for reason R.
If the finally block completes abruptly for reason S, then the try statement completes abruptly for reason S (and reason R is discarded).


According to section 14.1 (and 14.17) a return statement always completes abruptly.

Still, if you compile the first code sample with the Sun compiler and specify the -Xlint option (or -Xlint:finally) you should get a compiler warning something like: "warning: [finally] finally clause cannot complete normally". If anything that should be enough of an indication that the return-from-finally approach is rarely, if ever, appropiate.

Also, it might be worth noting that by returning from within a finally block you can inadvertantly discard unhandled exceptions thrown from within the try block.
[ December 30, 2008: Message edited by: Jelle Klap ]
 
kshitij dogra
Ranch Hand
Posts: 39
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Ruben.

what actually happening is, in code 1

- finally is always executed after try, (except when System.exit(0) is called). So, before the try block can return the value, finally is executed .

code 2
- You have mentioned the return statement after finally. As I told you in the previous case the call has to go to the return statement of the finally, and then the method call stack will collapse. This would cause the 3rd return statement , never to be executed......

Hence the error.
 
Ruben Soto
Ranch Hand
Posts: 1032
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by Jelle Klap:
Also, it might be worth noting that, aside from masking the return value of the try-block, any uncaught run-time exceptions that are thrown from inside the try-block are also discarded in this scenario.

Thanks for your answer, Jelle.
If I understand it correctly, the quote above means that the return statement in the finally block renders any potential runtime exceptions arising in the try block inconsequential (the method will return the expression in the finally block's return statement, and the program will proceed as if no runtime exception had been thrown, or as it had been caught in an empty catch block.)

I assume the same would be the case if any runtime exceptions are thrown in the catch block.

Very interesting.
[ December 30, 2008: Message edited by: Ruben Soto ]
 
Ruben Soto
Ranch Hand
Posts: 1032
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by kshitij dogra:
Hi Ruben.

what actually happening is, in code 1

- finally is always executed after try, (except when System.exit(0) is called). So, before the try block can return the value, finally is executed .

code 2
- You have mentioned the return statement after finally. As I told you in the previous case the call has to go to the return statement of the finally, and then the method call stack will collapse. This would cause the 3rd return statement , never to be executed......

Hence the error.

Thanks, kshitij. I understand what is going on. I was just wondering why the first case wouldn't cause a compiler error, but like Jelle mentioned it can cause a warning if javac is executed with the appropriate flag.
 
Jelle Klap
Bartender
Posts: 1951
7
Eclipse IDE Java
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by Ruben Soto:

Thanks for your answer, Jelle.
If I understand it correctly, the quote above means that the return statement in the finally block renders any potential runtime exceptions arising in the try or catch blocks inconsequential (the method will return the expression in the finally block's return statement, and the program will proceed as if no runtime exception had been thrown, or as it had been caught in an empty catch block.)

I assume the same would be the case if any runtime exceptions are thrown in the catch block.

Very interesting.


Well, I edited my previous post because I only mentioned RuntimeExceptions, and it really applies to all unhandled Throwables.
And yes, if a RuntimeException was to occur inside a catch block in such a situation it would be discarded.

Try this, contrived, example:



Compile and run, then disable the return from testDiscardThrowable's finally block and compile and run again.
[ December 30, 2008: Message edited by: Jelle Klap ]
 
Ruben Soto
Ranch Hand
Posts: 1032
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Great post, Jelle. Thanks a lot, it's clear now!
 
I agree. Here's the link: http://aspose.com/file-tools
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic