因此,我浏览了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类是否有好处?或仅仅是个人喜好。
答案 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模式时,这是最佳选择。