静态初始化器的性能几乎无关紧要(特别是对于这种琐碎的初始化),因为它只为一个类完成一次。
2)这个具体的方法做法是多余的,因为它是在类初始化时立即调用的;sdf
is alwaysnull 当静态初始化程序调用该方法时,并且您不会再次调用该方法(至少不是为了给出sdf
不同的值)。它也很糟糕,因为你故意读取未初始化的最终字段。
因此,只需删除条件,您最终会有效地返回到内联初始化程序方法,并间接调用方法。
例如,如果您想在格式化程序上进行其他配置(例如设置时区),则该方法会很有用。
3) 不要在构造函数中初始化静态成员。构造函数用于初始化实例成员。
特别是,这要求您将静态字段设置为非最终字段。这意味着您必须担心字段更新的可见性,以避免多个线程初始化字段,因为它们看到空值
4) 在声明时初始化字段只是声明静态初始化器的简写。问题中的第一个代码块在语义上与此相同:
private static final ComplexObject sdf;
static {
sdf = new ComplexObject();
}
如果你可以不这么做的话,明确地这样做并没有什么好处。
静态初始化器有点像匿名方法。 Google 的内部 Java 实践建议尽可能使用方法而不是显式静态初始化块,部分原因是您可以显式调用它们进行测试,但也因为它们必然会强制您仅初始化一个字段。 (我基本上同意这是一个很好的建议,但请注意,您会丢失方法中的明确赋值检查 - 正如上面所演示的 - 这可以帮助捕获某些类型的错误)。
结论:使用private static final ComplexObject sdf = new ComplexObject();
,因为你不需要任何更复杂的东西。
这里更大的问题是正确性,即确保sdf
不在线程之间共享:在编辑问题之前,sdf
was a SimpleDateFormat
,这不是线程安全的。我不知道什么ComplexObject
是,但您需要确保它是线程安全的,或者以线程安全的方式访问它。在进行微优化之前先担心类似的事情。