The initialization requirement is a formal part of Java, as described in the JLS:
For every access of a local variable or blank final field x, x must be definitely assigned before the access, or a compile-time error occurs.
(JLS 8, chapter 16; emphasis in the original)
The JLS goes on to say
The analysis takes into account the structure of statements and
expressions; it also provides a special treatment of the expression
operators !
, &&
, ||
, and ? :
, and of boolean-valued constant
expressions.
Except for the special treatment of the conditional boolean operators
&&
, ||
, and ? :
and of boolean-valued constant expressions, the values
of expressions are not taken into account in the flow analysis.
(emphasis added)
Note well that condition
being final
does not make it a "constant expression" as the specification defines that term. The specification goes on to give the specific rule for if
statements:
V
is [un]assigned after if (e) S
iff V
is [un]assigned after S
and V
is [un]assigned after e
when [e
evaluates to] false
.
In your particular code, then:
int myVar;
myVar
is definitely unassigned here.
final boolean condition = <someCondition>;
if (condition) {
myVar = 1;
}
myVar
is "assigned after S" because S, the body of the if
statement, performs an unconditional assignment. myVar
is not assigned after evaluation of the condition, however, whether the condition evaluates to true
or false
. Therefore, myVar
is not definitely assigned at this point in the method.
if (condition) {
And nothing has changed at this point: myVar
still is not definitely assigned as far as the JLS rules are concerned, so its value must not be read. The compiler is therefore obligated to report an error in the next statement:
System.out.println("myVar = " + myVar);
}