设计决策 - Math.java 中单独的 RandomNumberGenerator Holder class 的 use/advantage 是什么?

Design decision - What is the use/advantage of separate RandomNumberGeneratorHolder class in Math.java?

所以我在查看 Math.java 源代码时发现创建了一个容器 class 来保存 randomNumberGenerator 静态变量。这是相关的代码。

public final class Math {
 // other methods.
 public static double random() {
   return RandomNumberGeneratorHolder.randomNumberGenerator.nextDouble();
 }

 private static final class RandomNumberGeneratorHolder {
   static final Random randomNumberGenerator = new Random();
 }
}

IMO,我们可以简单地将 randomNumberGenerator 声明为 private static finalMath class 本身中。

我的问题是,为此创建一个单独的持有人 class 有什么好处吗?或者这只是个人喜好。

这是使用嵌套 classes 实现的惰性初始化单例的示例。

"holder" 在第一次调用 random() 时被初始化。第一次调用触发 RandomNumberGeneratorHolder class.

静态初始化的执行

(懒惰地这样做是值得的。在不提供种子的情况下初始化随机生成器需要去 OS 获取一些 "entropy" 来为生成器设置种子。这是一个相对昂贵的操作。您不希望 JVM 产生如果 random() 不会被调用的成本。)

这是initialisation-on-demand holder pattern的例子。当Math class被JVM加载时,Random实例不会立即被构造。相反,这只会在调用 random() 方法时发生,此时将加载 RandomNumberGenreatorHolder class,并构造 Random 单例对象。

本质上,代码确保 Random 单例是延迟创建的。

它们都是lazy,但一个是lazier(即单例模式)。拥有 private static 字段意味着当 class 持有该字段被初始化时,该字段也被初始化。因此,如果您需要在那个 class 上调用一个方法,但是 您不需要那个单例 ,它仍然会被初始化。

另一方面,嵌套 class 可以避免这种情况,实际使用时会对其进行初始化。

确切地说,这种情况很少见,jdk-本身很可能是极少数例子之一。

如本 post 的 answer 所述,holder 模式的目的是获取为 class 创建的单个实例,按需调用(延迟加载)并且也是线程安全的。当你想开发单例模式时,这是最好的选择。