【问题标题】:Design decision - What is the use/advantage of separate RandomNumberGeneratorHolder class in Math.java?设计决策 - Math.java 中单独的 RandomNumberGeneratorHolder 类的用途/优势是什么?
【发布时间】:2019-01-24 09:35:33
【问题描述】:

所以我浏览了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,我们可以简单地将 randomNumberGenerator 声明为 private static finalMath 类本身内。

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

【问题讨论】:

    标签: java java-8 design-decisions


    【解决方案1】:

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

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

    【讨论】:

    • 谢谢!这说得通。 :)
    【解决方案2】:

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

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

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

    【讨论】:

    • 感谢您的回答!很有帮助。
    【解决方案3】:

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

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

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

    【讨论】:

      【解决方案4】:

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

      【讨论】:

        猜你喜欢
        • 2012-10-05
        • 2016-04-16
        • 1970-01-01
        • 1970-01-01
        • 2020-01-16
        • 2015-12-06
        • 2020-02-07
        • 1970-01-01
        • 2019-02-19
        相关资源
        最近更新 更多