设计决策 - 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 final
在 Math
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 创建的单个实例,按需调用(延迟加载)并且也是线程安全的。当你想开发单例模式时,这是最好的选择。
所以我在查看 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 final
在 Math
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 创建的单个实例,按需调用(延迟加载)并且也是线程安全的。当你想开发单例模式时,这是最好的选择。