-
Bug
-
Resolution: Unresolved
-
P3
-
20
The handling of effectively final and blank final variables in the JLS differs slightly. In particular, for blank final variables, there's no assertion about definite assignment, only definite unassignment:
JLS 16:
For every assignment to a blank final variable, the variable must be definitely unassigned before the assignment, or a compile-time error occurs.
But, for effectively final variables, both definite assignment and unassignment are considered:
JLS 4.12.4.:
A local variable declared by a statement and whose declarator lacks an initializer is effectively final if all of the following are true:
...
Whenever it occurs as the left hand side in an assignment expression, it is definitely unassigned and not definitely assigned before the assignment; that is, it is definitely unassigned and not definitely assigned after the right hand side of the assignment expression (§16 (Definite Assignment)).
...
This leads to cases like:
int i; //note the variable can be marked final
if (false) {
i = 0; //this assignment makes the variable not effectively final, as "i" is definitely assigned and unassigned at the point when the assignment happens
} else {
i = 1;
}
Where a variable is not effectively final, but can be marked final, which is contrary to:
JLS 4.12.4.:
If a variable is effectively final, adding the final modifier to its declaration will not introduce any compile-time errors. Conversely, a local variable or parameter that is declared final in a valid program becomes effectively final if the final modifier is removed.
It would be good to evaluate if the JLS can be made more consistent.
JLS 16:
For every assignment to a blank final variable, the variable must be definitely unassigned before the assignment, or a compile-time error occurs.
But, for effectively final variables, both definite assignment and unassignment are considered:
JLS 4.12.4.:
A local variable declared by a statement and whose declarator lacks an initializer is effectively final if all of the following are true:
...
Whenever it occurs as the left hand side in an assignment expression, it is definitely unassigned and not definitely assigned before the assignment; that is, it is definitely unassigned and not definitely assigned after the right hand side of the assignment expression (§16 (Definite Assignment)).
...
This leads to cases like:
int i; //note the variable can be marked final
if (false) {
i = 0; //this assignment makes the variable not effectively final, as "i" is definitely assigned and unassigned at the point when the assignment happens
} else {
i = 1;
}
Where a variable is not effectively final, but can be marked final, which is contrary to:
JLS 4.12.4.:
If a variable is effectively final, adding the final modifier to its declaration will not introduce any compile-time errors. Conversely, a local variable or parameter that is declared final in a valid program becomes effectively final if the final modifier is removed.
It would be good to evaluate if the JLS can be made more consistent.
- blocks
-
JDK-8299416 javac complains about "local variables referenced from an inner class must be final or effectively final" although variable is only assigned once
- Open
- relates to
-
JDK-8294461 wrong effectively final determination by javac
- Resolved