java static final 会在多次初始化时出错吗?
Will java static final give error on multiple initializations?
我有一个 class 存储几个静态最终字段,如下所示:
class MyExampleClass{
public static final DateFormat T_FORMAT = new SimpleDateFormat("yyyy-mm-dd", Locale.ENGLISH);;
public static final logger LOGGER = new OwnLogger();
...
}
此代码 运行 作为 jboss(多线程)中的一项服务。有人指出,上面的代码可能会引发初始化错误,因为此 class 的所有实例都将引用相同的内存位置并尝试对其进行初始化。但是,由于变量是最终的,他们将无法这样做并抛出异常。
我尝试四处搜索,但找不到任何解决此查询的参考资料。所以我有以下问题:
1) 静态字段是 class 级变量,因此对于 class 的所有实例都是相同的。但是当我们在构造函数中初始化它们时,这是否意味着每次创建新实例时JVM都会用新值覆盖以前的值?
2) 如果我们覆盖字段(如上所问),final
应该会抛出错误吗?
3) 假设我们没有覆盖:一旦 class 显式覆盖静态字段内容,所有其他 class 都会看到相同的值。但这个新价值能持续多久?直到所有的实例都被杀死并且在一些延迟之后我们实例化一个新的?还是永远?
我很困惑。非常感谢任何帮助!
A class 只初始化一次,并且是线程安全的。
有strong guarantees about this in the Java Language Specification.
The implementation of the Java Virtual Machine is responsible for
taking care of synchronization and recursive initialization by using
the following procedure.
所以有 final static
个字段很好,你不会出错的。 以至于它有时被利用来提供线程安全的单例,通过 static holder pattern。 该字段将被初始化一次并且每个人都会看到该字段的相同值*。出于实际目的,您可以假设该字段一直存在并将永远存在。
另一方面,从实例方法(包括构造函数)向 static
字段写入数据通常是一个很大的禁忌。
*当这不是真的时,有一些模糊的场景,但你不需要担心它们,除非你在静态初始化器之间有循环依赖,无论如何你都不应该有。
我有一个 class 存储几个静态最终字段,如下所示:
class MyExampleClass{
public static final DateFormat T_FORMAT = new SimpleDateFormat("yyyy-mm-dd", Locale.ENGLISH);;
public static final logger LOGGER = new OwnLogger();
...
}
此代码 运行 作为 jboss(多线程)中的一项服务。有人指出,上面的代码可能会引发初始化错误,因为此 class 的所有实例都将引用相同的内存位置并尝试对其进行初始化。但是,由于变量是最终的,他们将无法这样做并抛出异常。
我尝试四处搜索,但找不到任何解决此查询的参考资料。所以我有以下问题:
1) 静态字段是 class 级变量,因此对于 class 的所有实例都是相同的。但是当我们在构造函数中初始化它们时,这是否意味着每次创建新实例时JVM都会用新值覆盖以前的值?
2) 如果我们覆盖字段(如上所问),final
应该会抛出错误吗?
3) 假设我们没有覆盖:一旦 class 显式覆盖静态字段内容,所有其他 class 都会看到相同的值。但这个新价值能持续多久?直到所有的实例都被杀死并且在一些延迟之后我们实例化一个新的?还是永远?
我很困惑。非常感谢任何帮助!
A class 只初始化一次,并且是线程安全的。
有strong guarantees about this in the Java Language Specification.
The implementation of the Java Virtual Machine is responsible for taking care of synchronization and recursive initialization by using the following procedure.
所以有 final static
个字段很好,你不会出错的。 以至于它有时被利用来提供线程安全的单例,通过 static holder pattern。 该字段将被初始化一次并且每个人都会看到该字段的相同值*。出于实际目的,您可以假设该字段一直存在并将永远存在。
另一方面,从实例方法(包括构造函数)向 static
字段写入数据通常是一个很大的禁忌。
*当这不是真的时,有一些模糊的场景,但你不需要担心它们,除非你在静态初始化器之间有循环依赖,无论如何你都不应该有。