Является ли последнее ключевое слово необходимым в классе singleton Java?

public class MySingleton{
  private static final MySingleton INSTANCE = new MySingleton();
  private MySingleton(){}
  public static getInstance(){
    return INSTANCE;
  }
}

Это правильный способ реализовать Singleton. Если да, то в чем заключается необходимость последнего ключевого слова?

Ответ 1

Final гарантирует, что экземпляр не будет изменяться после создания. Если вы включаете только конструктор и нет сеттеров, это не имеет большого значения. Никто не может изменить вашу INSTANCE, и вы не меняете ее.

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

Труднее вернуть неизменность, чем вынести ее. Напиши свой код в обороне, чтобы никто не мог испортить его позже.

Ответ 2

Обычно предпочтительный подход заключается в использовании перечисления

public enum MySingleton {
    INSTANCE;
}

В вашем примере ключевое слово final показывает намерение и предотвратит переназначение (= ошибка), но не является строго необходимым.

В частности, переменная, являющаяся статичной, не обязательно должна быть окончательной, чтобы ее можно было безопасно опубликовать в многопоточной среде.

Ответ 3

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

Если модульное тестирование является проблемой, и вы все еще хотите использовать одноэлемент, подумайте об использовании инъекции зависимостей. Это позволит вам настроить обычный экземпляр с жизненным циклом singleton.

Окончательный модификатор позволяет компилятору Java и времени выполнения эффективно оптимизировать и принимать решения по обеспечению безопасности потоков. Я бы всегда использовал final с этим стилем объявления singleton. Я бы зашел так далеко, что сказал, что это плохой выбор дизайна, позволяющий экземпляру singleton быть изменчивым, потому что клиентский код больше не может полагаться на то же самое значение для времени жизни процесса.

С проблемой модульного тестирования можно справиться с настраиваемым классом factory:

private static final MySingleton INSTANCE = MySingletonFactory.create();

... без потери преимуществ финального.

Ответ 4

не обязательно. но используя final, он не может быть reset самим классом singleton, который обеспечивает истинную синглтон. Однако, поскольку синглтоны - это плохая практика, их можно использовать для модульных тестов, добавив метод setInstance(). Обеспокоенные люди могут определять setInstance private, так что unit test вызывает setInstance через отражение.