java - 在构造函数之外初始化的最终字段是否会在运行构造函数之前初始化?

标签 java multithreading thread-safety visibility safe-publication

假设你有这个代码片段

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


SomeConstructor() {
   printSet();
}

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

例如,如果编译器决定使其看起来像

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

这将是一个问题,因为calculateWaitTime()创建一个新线程,该线程可能会将集合视为null或其中没有1。

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

最佳答案

final 字段不可能。

看看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.

但是您也可以看到,它不能保证使用反射进行后续的final字段修改。请参阅17.5.3了解更多详情。

关于java - 在构造函数之外初始化的最终字段是否会在运行构造函数之前初始化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48658540/

相关文章:

java - 如何从 Deeplearning4J 的 org.datavec.audio.Spectrogram 生成频谱图图像?

Android AsyncTask 上下文行为

java - 步骤仅在任务执行器的一个线程上运行。

java - Cipher 线程安全吗?

Java Commons.net 和 FTP 权限

java - 如何使用预准备语句修复 SQL 注入(inject)?

Java thread.sleep(1) sleep 时间超过 1 毫秒

java - H2 使用线程时内存数据库不一致

c# - java、c#、vb : Can we write thread safety functions without relying on native implementations

Java 游戏 - 按下鼠标并拖动鼠标