Community
Participate
Working Groups
When returning from within a finally{} block, the Eclipse compiler does not complain about an Exception that is not declared to be thrown, but javac does. Interestingly, the output of both programs (if I declare the throws) is "Shouldn't get here", so in that regard the compilers are consistent. Despite what the JLS might say about the issue (I am not a JLS expert), the bahavior of both compilers seems pretty wrong to me. I don't like that the Exception gets "eaten" without an explicit catch. I figured I should report the inconsistency. I of course defer to Phillip (or whoever :) ) to determine if it's really a compiler bug, since I have seen more than one report be explained by slightly different interpretations of vague JLS points. The error reported by javac 1.3.1 is: javac com\test\FinallyExceptionTest.java com\test\FinallyExceptionTest.java:19: unreported exception java.lang.Exception; must be caught or d eclared to be thrown throw new Exception("Exception"); ^ 1 error Test case: package com.test; public class FinallyExceptionTest { public static void main(String[] arguments) { try { FinallyExceptionTest t = new FinallyExceptionTest(); System.out.println("I shouldn't get here"); } catch (Exception e) { e.printStackTrace(); } } public void doSomething() { try { throw new Exception("Exception"); } finally { return; } } }
Ooops, there should also be a call to t.doSomething() in there. I was playing with the test case, but the other points remain the same. The correct test case is: package com.test; public class FinallyExceptionTest { public static void main(String[] arguments) { try { FinallyExceptionTest t = new FinallyExceptionTest(); t.doSomething(); System.out.println("I shouldn't get here"); } catch (Exception e) { e.printStackTrace(); } } public void doSomething() { try { throw new Exception("Exception"); } finally { return; } } }
Finally block have to be run during exception handling, and may cause abrupt termination of method. This is the language specified behavior. Technically, a finally block is not much different from a catch block which is ensured to be both on the exception and normal termination execution path. In cases, this can become convenient to replace an exception with another one. try { throw new A(); } finally { throw new B(); } Returning finally blocks can easily become counter-intuitive: try { return 1; } finally { return 2; // 2 will be returned } A good programming style is probably to avoid returning directly from whithin finally blocks. Now for the compiler behavior, I would say our behavior is the proper one, in the sense it matches the runtime silent absorption of the exception. Will investigate some more.
This behavior as I observed in JDK 1.4 also shows the problem. /** * @author Sanjay Madhavan * * Test case to show a problem/feature? with exception handling and * method signatures when a finally block is specified. * This behavior is observed in Eclipse Version: 2.0 Build id: 200208201620 * * The Sun java compiler in JDK version "1.4.0_01" correctly flags the * testExceptionWronglyCompiles method as incorrect. */ public class TestException { /* * This method will compile. This is correct behavior */ public String testExceptionCorrect() throws Exception { throw new Exception(); } /* * This method will not compile. This is correct behavior */ public String testExceptionWillNotCompile() { if (true) throw new Exception(); return "bogus"; } /* * This method will compile. This to me is INCORRECT behavior. */ public String testExceptionWronglyCompiles() { try { throw new Exception(); } catch (Exception me) { throw me; } finally { // the return within the finally seems to confuse the compiler return "bogus"; } } public static void main(String[] args) { TestException test = new TestException(); System.out.println( "testExceptionWronglyCompiles returned: " + test.testExceptionWronglyCompiles()); } }
Sanjay - What makes you think our compiler is wrong ? When running the offending method, do you get any uncaught exception stack trace ? No, because the exception is never surfaced beyond the finally block. Javac doesn't notice it, we do.
Just for the record (I can't speak for Sanjay), but I actually think Eclipse's interepretation is more "technically correct". I just reported the bug to note the inconsistency as people get upset when something compiles in Eclipse and not with javac/jikes or vice versa. I am a little dissapointed this can happen at all according to the JLS. Throughout the language, Java is very careful to ensure exceptions are handled through some purposeful action (catch/throw), and in this case you can "accidentally" not handle an exception. Some well-meaning programmer on my project was trying to fix a "JTest" error (static code analysis) which complained there were too many return statements in the method. Instead of improving the code, though, it caused a very subtle bug with the exceptional conditions. Of course, once I noticed the return in the finally... -Andrew
Closing, behaving as expected.
*** Bug 46421 has been marked as a duplicate of this bug. ***
We added a warning to signal that the finally block is not completing normally.