7
public class Test {

    private static final int A;

    static {
        A = 5;
    }
}

This way of initializing static final variable A works okay .

public class Test {
    private static final int A;

    static {
        Test.A = 5;
    }   
}

This way gives compile error "Cannot assign a value to final variable 'A'.

Why?

  • Not sure, but possibly because to do Test.A = 5, you would need an instance of Test. And you cannot assign the value after the instance is created. – Alper Akture Mar 06 '18 at 20:41
  • 3
    @AlperAkture: No, that doesn't require an instance of `Test`. – Jon Skeet Mar 06 '18 at 20:45
  • That's a main point of static, no instance involved. – takendarkk Mar 06 '18 at 20:45
  • 2
    I would not mind that much. Code like that is super rare, you don't really need it. I'm sure it is some technical issue and has to do with the exact way JLS defines things, probably has to do with when exactly a `static` block gets executed and when you can reference using `Test.A`. Nonetheless, interesting spot and I'm curios for a detailed answer too. – Zabuzard Mar 06 '18 at 20:46

1 Answers1

8

Specified by the rules for Definite Assignment:

Let C be a class, and let V be a blank static final member field of C, declared in C. Then:

  • V is definitely unassigned (and moreover is not definitely assigned) before the leftmost enum constant, static initializer (§8.7), or static variable initializer of C.

  • V is [un]assigned before an enum constant, static initializer, or static variable initializer of C other than the leftmost iff V is [un]assigned after the preceding enum constant, static initializer, or static variable initializer of C.

In layman's terms:

  • Using a static initializer to initialize a static final field by referencing its simple name is OK since that field is definitely assigned after the initializer. Effectively, there's context into the class in which the static initializer is declared in, and you are not performing any illegal assignment by referring to the field by its simple name; instead, you're fulfilling the requirement that the field must be definitely assigned.

  • Using a static initializer to initialize a static final field by referencing its qualified name is illegal, since the class must be initialized when referring to a static property of it (in your case, Test.A must be initialized prior, and A is assigned the default value of null upon completion of initialization).

Makoto
  • 104,088
  • 27
  • 192
  • 230