Search code examples
javamultithreadingthread-safetyvisibilitysafe-publication

Do final fields initialized outside of constructors get initialized before running the constructor?


Say you have this code snippet

private final Set set = new HashSet() {{ add(1); }};


SomeConstructor() {
   printSet();
}

long printSet() {
    new Thread(() -> {System.out.println(set)}).start();
}

for example if the compiler decided to make this look like

private final Set set;
SomeConstructor() {
   printSet();
   set = new HashSet() {{ add(1); }};
}

this would be a problem because calculateWaitTime() makes a new Thread that might see the set as null or not having a 1 in it.

So the question again, is this reordering possible? Or do all final fields initialized outside of the constructor get initialized before the constructor or at least moved to the top of the constructor always by the compiler


Solution

  • It's not possible for final fields.

    Just look at The Java ® Language Specification Java SE 8 Edition > 17.5.2 Reading final Fields During Construction:

    17.5.2 Reading final Fields During Construction

    A read of a final field of an object within the thread that constructs that object is ordered with respect to the initialization of that field within the constructor by the usual happens-before rules. If the read occurs after the field is set in the constructor, it sees the value the final field is assigned, otherwise it sees the default value.

    But as you also can see it's not guarantied for subsequent final field modifications using reflection. See 17.5.3 for more details.