Tuesday, 18 September 2012

Puzzle 36: Indecision


This poor little program can't quite make up its mind. The decision method returns true. But it also returns false. What does it print? Is it even legal?
public class Indecisive {

    public static void main(String[] args) {

        System.out.println(decision());

    }



    static boolean decision() {

        try {

            return true;

        } finally {

            return false;

        }

    }

}


Solution 36: Indecision

You might think that this program is illegal. After all, the decision method can't return both TRue and false. If you tried it, you found that it compiles without error and prints false. Why?
The reason is that in a try-finally statement, the finally block is always executed when control leaves the try block [JLS 14.20.2]. This is true whether the try block completes normally or abruptly. Abrupt completion of a statement or block occurs when it throws an exception, executes a break or continue to an enclosing statement, or executes a return from the method as in this program. These are called abrupt completions because they prevent the program from executing the next statement in sequence.
When both the TRy block and the finally block complete abruptly, the reason for the abrupt completion in the try block is discarded, and the whole TRy-finally statement completes abruptly for the same reason as the finally block. In this program, the abrupt completion caused by the return statement in the TRy block is discarded, and the TRy-finally statement completes abruptly because of the return statement in the finally block. Simply put, the program tries to return true but finally it returns false.
Discarding the reason for abrupt completion is almost never what you want, because the original reason for abrupt completion might be important to the behavior of a program. It is especially difficult to understand the behavior of a program that executes a break, continue, or return statement in a TRy block only to have the statement's behavior vetoed by a finally block.
In summary, every finally block should complete normally, barring an unchecked exception. Never exit a finally block with a return, break, continue, or tHRow, and never allow a checked exception to propagate out of a finally block.
For language designers, finally blocks should perhaps be required to complete normally in the absence of unchecked exceptions. Toward this end, a TRy-finally construct would require that the finally block can complete normally [JLS 14.21]. A return, break, or continue statement that transfers control out of a finally block would be disallowed, as would any statement that could cause a checked exception to propagate out of the finally block.

No comments:

Post a Comment

Your comments are welcome!