JDK-8299861 : Inconsistent handling of effectively final and blank final variables
  • Type: Bug
  • Component: specification
  • Sub-Component: language
  • Affected Version: 20
  • Priority: P3
  • Status: Open
  • Resolution: Unresolved
  • Submitted: 2023-01-10
  • Updated: 2024-12-05
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other
tbdUnresolved
Related Reports
Blocks :  
Relates :  
Description
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.