关于java:在构造函数运行之前,在构造函数之外初始化的最终字段是否已初始化?

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

本问题已经有最佳答案,请猛点这里访问。

假设您有此代码段

1
2
3
4
5
6
7
8
9
10
private final Set set = new HashSet() {{ add(1); }};


SomeConstructor() {
   printSet();
}

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

例如,如果编译器决定将此设置为

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

这将是一个问题,因为calculateWaitTime()生成一个新线程,该线程可能会将集合视为空或不包含1。

那么问题又来了,这种重新排序是可能的吗?或者,是否所有在构造函数外部初始化的最终字段都在构造函数之前初始化,或者至少总是由编译器移到构造函数的顶部


对于final字段是不可能的。

只需看看7.5.2在构建过程中读取最后的字段"> Java?语言规范JAVE SE 8版> 7.5.2在施工期间阅读最终字段:

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.

但正如你所看到的,它不能保证随后使用反射对final场进行修改。详见17.5.3。