Постарайтесь не инстанцировать класса в Java

Примечание: статичный синхронизированные методы и блоки работают над Объектом класса.

public class MyClass {
   // locks MyClass.class
   public static synchronized void foo() {
// do something
   }

   // similar
   public static void foo() {
      synchronized(MyClass.class) {
// do something
      }
   }
}
19
задан Community 23 May 2017 в 12:22
поделиться

5 ответов

На ум приходят четыре причины:

  1. Разрешить создание экземпляров подклассов, но не родительского;
  2. Запретить прямое создание экземпляров и вместо этого предоставить фабричный метод для вернуть и при необходимости создать экземпляры;
  3. Поскольку все экземпляры предопределены (например, масти в колоде карт), хотя, начиная с Java 5, вместо них рекомендуются типы безопасных перечислений; и
  4. Класс действительно не является классом. Это просто держатель для статических констант и / или методов.

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

public class MyColor {
  private final int red, green, blue;

  private MyColor(int red, int green, int blue) {
    this.red = red;
    this.green = green;
    this.blue = blue;
  }

  public static MyColor getInstance(int red, int green, int blue) {
    // if combo already exists, return it, otherwise create new instance
  }
}

Примечание: конструктор без аргументов не требуется, потому что другой конструктор определен явно.

28
ответ дан 30 November 2019 в 02:56
поделиться

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

3
ответ дан 30 November 2019 в 02:56
поделиться

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

2
ответ дан 30 November 2019 в 02:56
поделиться

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

Вы хотите, чтобы класс не был инстанцируемым, если нет смысла его инстанцировать. Обычно вы делаете это, если класс действительно является просто набором (статических) вспомогательных методов или если класс «неполный». Неполнота может быть синтаксически очевидной (например, абстрактные методы), но есть и другие виды неполноты. Например, вы можете предоставить реализации по умолчанию для всех методов и потребовать, чтобы один или несколько из них были переопределены для того, чтобы класс делал что-то полезное.

Еще одна причина сделать класс не имеющим возможности создания экземпляров (или, по крайней мере, не создается напрямую), если вашему приложению необходимо управлять созданием экземпляра. Например, нельзя напрямую создать экземпляр класса java.util.regex.Pattern, чтобы JRE могла (могла) поддерживать кеш предварительно скомпилированных регулярных выражений.

1
ответ дан 30 November 2019 в 02:56
поделиться

Не совсем ответ на ваш вопрос, а просто примечание:

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

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

11
ответ дан 30 November 2019 в 02:56
поделиться
Другие вопросы по тегам:

Похожие вопросы: