Java Reference
In-Depth Information
}
}
class IdUnavailableException extends Exception {
IdUnavailableException() { }
}
Solution 38: The Unwelcome Guest
This program seems straightforward. The call to
getUserIdFromEnvironment
appears to throw an
exception, causing the program to assign the value of
GUEST_USER_ID
(
-1L
) to
USER_ID
and to print
Logging in as guest
. Then the
main
method executes, causing the program to print
User ID: -1
.
Once again, appearances are deceiving. The program doesn't compile. If you tried to compile it, you
saw an error message that looked something like this:
UnwelcomeGuest.java:10:
variable USER_ID might already have been assigned
USER_ID = GUEST_USER_ID;
^
What's the problem? The
USER_ID
field is a
blank final
, which is a final field whose declaration
lacks an initializer [JLS 4.12.4]. It is clear that the exception can be thrown in the
try
block only if
the assignment to
USER_ID
fails, so it is perfectly safe to assign to
USER_ID
in the
catch
block. Any
execution of the static initializer block will cause exactly one assignment to
USER_ID
, which is just
what is required for blank finals. Why doesn't the compiler know this?
Determining whether a program can perform more than one assignment to a blank final is a hard
problem. In fact, it's impossible. It is equivalent to the classic
halting problem
, which is known to
be unsolvable in general
[Turing36]
. To make it possible to write a Java compiler, the language
specification takes a conservative approach to this issue.
A blank final field can be assigned only
at points in the program where it is
definitely unassigned
.
The specification goes to great lengths
to provide a precise but conservative definition for this term [JLS 16]. Because it is conservative,
there are some provably safe programs that the compiler must reject.
This puzzle illustrates one
such program.
Search WWH ::
Custom Search