4

所以我浏览了Math.java源代码,我发现创建了一个持有者类来保存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,我们可以简单地在类本身中声明randomNumberGeneratoras 。private static finalMath

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

4

4 回答 4

10

这是按需初始化持有者模式的一个示例。当Math类被JVM加载时,Random不会立即构造实例。相反,只有在调用方法时才会发生这种情况random(),此时RandomNumberGenreatorHolder将加载类并Random构造单例对象。

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

于 2018-08-17T10:54:23.843 回答
4

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

另一方面,拥有一个嵌套类可以防止这种情况发生,并且在实际使用时会被初始化。

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

于 2018-08-17T10:55:12.100 回答
3

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

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

(懒惰地这样做是值得的。在不提供种子的情况下初始化随机生成器需要去操作系统获取一些“熵”来为生成器播种。这是一个相对昂贵的操作。你不希望 JVM 产生这样的成本ifrandom()不会被调用。)

于 2018-08-17T10:54:06.370 回答
1

正如这篇文章的答案所提到的,持有者模式的目的是为该类创建一个实例,按需调用(延迟加载)并且也是线程安全的。当您想开发单例模式时,它是最佳选择。

于 2018-08-17T11:05:46.057 回答