Some may find it similar to the SO question Will Java Final variables have default values? but that answer doesn\'t completely solve this, as that question doesn\'t directl
Reading the JLS, the answer appears to be in section 16.2.2:
A blank
finalmember fieldVis definitely assigned (and moreover is not definitely unassigned) before the block (§14.2) that is the body of any method in the scope ofVand before the declaration of any class declared within the scope ofV.
This means that when a method is called, the final field is assigned to its default value 0 before invoking it, so when you reference it inside the method, it compiles successfully and prints the value 0.
However, when you access the field outside of a method, it is considered unassigned, hence the compilation error. The following code will also not compile:
public class Main {
final int x;
{
method();
System.out.println(x);
x = 7;
}
void method() { }
public static void main(String[] args) { }
}
because:
Vis [un]assigned before any other statementSof the block iffVis [un]assigned after the statement immediately precedingSin the block.
Since the final field x is unassigned before the method invocation, it is still unassigned after it.
This note in the JLS is also relevant:
Note that there are no rules that would allow us to conclude that
Vis definitely unassigned before the block that is the body of any constructor, method, instance initializer, or static initializer declared inC. We can informally conclude thatVis not definitely unassigned before the block that is the body of any constructor, method, instance initializer, or static initializer declared in C, but there is no need for such a rule to be stated explicitly.