Проектное решение - Каково использование / преимущество отдельного класса RandomNumberGeneratorHolder в Math.java?

Так что я проходил через 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();
 }
}

ИМО, мы могли бы просто объявить randomNumberGenerator как private static final внутри Math сам класс.

У меня вопрос: есть ли преимущество для создания отдельного класса держателей для этого? Или это просто личное предпочтение.

4 ответа

Решение

Это пример шаблона держателя инициализации по требованию. Когда Math класс загружается JVM, Random Экземпляр не будет построен сразу. Вместо этого это произойдет только тогда, когда random() метод вызывается, в этот момент RandomNumberGenreatorHolder класс будет загружен, а Random синглтон объект построен.

По сути, код гарантирует, что Random Синглтон создан лениво.

Они оба lazy, но один lazier (шаблон синглтона, который есть). Иметь private static Поле будет означать, что, когда класс, содержащий это поле, инициализируется, это поле также инициализируется. Поэтому, если вам нужно вызвать метод для этого класса, но вам не нужен этот синглтон, он все равно будет инициализирован.

С другой стороны, наличие вложенного класса предотвратит это и будет инициализировано при фактическом использовании.

Чтобы быть точным, это очень редко, когда это имеет значение, и сам jdk, скорее всего, является одним из очень немногих примеров.

Это пример лениво-инициализированного синглтона, который реализован с использованием вложенных классов.

"Держатель" инициализируется при первом random() называется. Первый вызов запускает выполнение статической инициализации RandomNumberGeneratorHolder учебный класс.

(Это стоит делать лениво. Инициализация генератора случайных чисел без предоставления начального числа влечет за собой переход к ОС для получения некоторой "энтропии" для начального заполнения генератора. Это относительно дорогая операция. Вы не хотите, чтобы JVM понесла такую ​​стоимость, что если random() не будет называться.)

Как упоминалось в ответе на этот пост, цель паттерна-держателя состоит в том, чтобы создать отдельный экземпляр, созданный для этого класса, вызов по требованию (отложенная загрузка), а также поточно-ориентированный. Это лучший вариант, когда вы хотите разработать шаблон Singleton.

Другие вопросы по тегам