设计决策-Math.java中单独的RandomNumberGeneratorHolder类的用途/优点是什么?

时间:2018-08-17 10:48:19

标签: java java-8 design-decisions

因此,我浏览了Math.java源代码,发现发现创建了一个holder类来保存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 final声明为Math

我的问题是,为此创建一个单独的holder类是否有好处?或仅仅是个人喜好。

4 个答案:

答案 0 :(得分:8)

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

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

答案 1 :(得分:4)

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

另一方面,使用嵌套类可以防止这种情况发生,并且在实际使用时会对其进行初始化。

确切地说,在这种情况下,这种情况很少发生,并且jdk-itself很可能是极少数示例之一。

答案 2 :(得分:3)

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

第一次调用random()时,将初始化“持有人”。第一次调用触发RandomNumberGeneratorHolder类的静态初始化的执行。

(这是值得做的懒惰。在不提供种子的情况下初始化随机生成器需要进入OS以获得一些“熵”来为生成器提供种子。这是一个相对昂贵的操作。您不希望JVM发生如果不调用random()的费用。)

答案 3 :(得分:1)

如本文的answer中所述,holder模式的目的是为该类创建一个实例,按需调用(延迟加载),并且也是线程安全的。当您要开发Singleton模式时,这是最佳选择。