当前位置: 首页 > 知识库问答 >
问题:

在构造函数外部初始化的最终字段是否在运行构造函数之前初始化?[重复]

阚通
2023-03-14

假设你有这个代码片段

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。

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

共有1个答案

韩博厚
2023-03-14

final字段是不可能的。

只需看看17.5.2在构建过程中读取最终字段“>Java®语言规范Java SE 8版本

17.5.2施工期间读取最终字段

在构造该对象的线程中,读取该对象的最后一个字段的顺序与构造函数中该字段的初始化顺序有关,按照通常的before规则执行。如果读取发生在构造函数中设置字段之后,则会看到最后一个字段分配的值,否则会看到默认值。

但正如您也可以看到的,它并不能保证后续使用反射进行final字段修改。详见17.5.3。

 类似资料:
  • 问题内容: 谁能解释以下程序的输出?我认为构造函数要在实例变量之前初始化。因此,我期望输出为“ XZYY”。 问题答案: 正确的初始化顺序是: 如果该类先前尚未初始化,则按文本顺序的静态变量初始化程序和静态初始化块。 构造函数中的super()调用,无论是显式的还是隐式的。 实例变量初始化程序和实例初始化块,按文本顺序。 super()之后构造函数的其余主体。

  • 有人能解释一下以下程序的输出吗?我以为构造函数是在实例变量之前初始化的。所以我希望输出是“xzy”。

  • 问题内容: 有没有在Java构造函数中使用最终变量的解决方案?问题是,如果我初始化一个最终字段,例如: 那么我就不能在构造函数中使用它。Java首先运行构造函数,然后运行字段。有没有一种解决方案可以让我访问构造函数中的final字段? 问题答案: 我不太明白你的问题。那 执行如下:

  • 问题内容: 如果未将ArrayList初始化为字段,则将项目添加到ArrayList时出现NullPointerException。谁能解释为什么? 当我将ArrayList初始化为字段时起作用: 当我将ArrayList声明为字段然后在Class构造函数中对其进行初始化时,它不起作用: 问题答案: 因为构造函数中的版本正在创建一个新变量,而该变量恰好与您的成员字段名称相同,而成员字段仍未设置。这

  • 问题内容: 假设我有 什么时候初始化?之前,之后,取决于? 如果我有一个与的全局定义冲突的构造函数,例如在上面的第三个构造函数中,该怎么办?取哪个值? 这不会给我造成任何问题,但我只是想更好地理解该语言。我喜欢了解这些小知识,以便以后可以潜在地利用它们。 问题答案: 变量被初始化为其类型的默认值(0,null等) 首先,调用超类构造函数。如果超类构造函数调用任何在该类中重写的虚拟方法,则该重写将看

  • 问题内容: 我有两个班,第一个是我的主班,第二个是我的编辑框架班。 我的第二个类(UpdateGUI)在其构造函数中提供oldName,并对其进行编辑,当我单击时,它将newName发送给我的第一个类。 我的第二堂课: 我的问题是,为什么newName为null? 更新: UpdateGUIDialog类: 输出: 我需要打印而不是null。 问题答案: Java对象有点像真实对象。并顾名思义:它