Why can't we access static content via uninitialized local variable?

§15.11. Field Access Expressions:

If the field is static:

The Primary expression is evaluated, and the result is discarded. If evaluation of the Primary expression completes abruptly, the field access expression completes abruptly for the same reason.

Where earlier it states that field access is identified by Primary.Identifier.

This shows that even though it seems to not use the Primary, it is still evaluated and the result is then discarded which is why it will need to be initialized. This can make a difference when the evaluation halts the access as stated in the quote.

EDIT:

Here is a short example just to demonstrate visually that the Primary is evaluated even though the result is discarded:

class Foo {
    public static int x = 1;
    
    public static Foo dummyFoo() throws InterruptedException {
        Thread.sleep(5000);
        return null;
    }
    
    public static void main(String[] args) throws InterruptedException {
        System.out.println(dummyFoo().x);
        System.out.println(Foo.x);
    }
}

Here you can see that dummyFoo() is still evaluated because the print is delayed by the 5 second Thread.sleep() even though it always returns a null value which is discarded.

If the expression was not evaluated the print would appear instantly, which can be seen when the class Foo is used directly to access x with Foo.x.

Note: Method invocation is also considered a Primary shown in §15.8 Primary Expressions.


Chapter 16. Definite Assignment

Each local variable (§14.4) and every blank final field (§4.12.4, §8.3.1.2) must have a definitely assigned value when any access of its value occurs.

It doesn't really matter what you try to access via a local variable. The rule is that it should be definitely assigned before that.

To evaluate a field access expression foo.x, the primary part of it (foo) must be evaluated first. It means that access to foo will occur, which will result in a compile-time error.

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.


There is value in keeping the rules as simple as possible, and “don’t use a variable that might not have been initialised” is as simple as it gets.

More to the point, there is an established way of calling static methods - always use the class name, not a variable.

System.out.println(Foo.x);

The variable “foo” is unwanted overhead that should be removed, and the compiler errors and warnings could be seen as helping leading towards that.