java static final会在多次初始化时出错吗?

时间:2016-06-16 10:11:04

标签: java multithreading static final

我有一个类,它存储了几个静态最终字段,如下所示:

class MyExampleClass{
  public static final DateFormat T_FORMAT = new SimpleDateFormat("yyyy-mm-dd", Locale.ENGLISH);;
  public static final logger LOGGER = new OwnLogger();
 ...
}

此代码作为jboss(多线程)内部的服务运行。有人指出,上面的代码可能会抛出初始化错误,因为此类的所有实例都将引用相同的内存位置并尝试初始化它。但是,由于变量是最终的,他们将无法抛出异常。

我尝试搜索但找不到任何解决此查询的引用。所以我有以下问题:

1)静态字段是类级变量,因此对于该类的所有实例都是相同的。但是当我们在构造函数中初始化它们时,这是否意味着每次创建新实例时JVM都会用新的值覆盖前一个值?

2)如果我们覆盖了字段(如上所述),final应该抛出错误吗?

3)假设我们没有过度编写:一旦一个类显式覆盖了静态字段内容,所有其他类都会看到相同的值。但这个新价值能持续多久?直到所有的实例都被杀死并且经过一段时间的延迟我们实例化一个新实例?还是永远?

我很困惑。非常感谢任何帮助!

1 个答案:

答案 0 :(得分:3)

一个类只能以线程安全的方式初始化一次。

strong guarantees about this in the Java Language Specification

  

Java虚拟机的实现负责   通过使用来处理同步和递归初始化   以下程序。

因此,final static字段很好,你就不会出错。 以至于它有时被利用来提供线程安全的单例,通过static holder pattern该字段将被初始化一次,每个人都会看到字段*的相同值。出于实际目的,您可以假设该领域始终存在并将永远存在。

另一方面,从实例方法(包括构造函数)向static字段写入数据通常是一个很大的禁忌。

*如果不是这样,有一些不起眼的情况,但你不需要担心它们,除非你在静态初始化者之间存在循环依赖关系,你不应该这样做。