Примечание: статичный синхронизированные методы и блоки работают над Объектом класса.
public class MyClass {
// locks MyClass.class
public static synchronized void foo() {
// do something
}
// similar
public static void foo() {
synchronized(MyClass.class) {
// do something
}
}
}
На ум приходят четыре причины:
В качестве примера (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
}
}
Примечание: конструктор без аргументов не требуется, потому что другой конструктор определен явно.
Иногда вы хотите только избежать создания экземпляров ваших объектов другими, чтобы иметь полный контроль над всеми существующими экземплярами. Одним из примеров является одноэлементный шаблон .
Я думаю, что наиболее распространенная причина нежелания создавать экземпляр класса - это когда вы имеете дело со статическим классом и, следовательно, с его статическими методами. Вы же не хотите, чтобы кто-то пытался создать экземпляр этого класса. Аналогичным образом, когда вы имеете дело с классами Factory или в некоторых случаях многие синглтон-классы будут скрывать свой конструктор, чтобы не создавать их обычным способом.
Другой способ сделать класс не имеющим отношения к экземпляру - объявить его как частный внутренний класс, а затем не предоставлять никакого способа создать его экземпляр в окружающем классе. Но это (ИМО) довольно бессмысленно.
Вы хотите, чтобы класс не был инстанцируемым, если нет смысла его инстанцировать. Обычно вы делаете это, если класс действительно является просто набором (статических) вспомогательных методов или если класс «неполный». Неполнота может быть синтаксически очевидной (например, абстрактные методы), но есть и другие виды неполноты. Например, вы можете предоставить реализации по умолчанию для всех методов и потребовать, чтобы один или несколько из них были переопределены для того, чтобы класс делал что-то полезное.
Еще одна причина сделать класс не имеющим возможности создания экземпляров (или, по крайней мере, не создается напрямую), если вашему приложению необходимо управлять созданием экземпляра. Например, нельзя напрямую создать экземпляр класса java.util.regex.Pattern, чтобы JRE могла (могла) поддерживать кеш предварительно скомпилированных регулярных выражений.
Не совсем ответ на ваш вопрос, а просто примечание:
Когда вы создаете частный конструктор без аргументов для предотвращения создания экземпляров ваших служебных классов , конструктор должен генерировать исключение (например, UnsupportedOperationException). Это потому, что вы можете получить доступ к закрытым членам (включая конструкторы) через отражение. Обратите внимание, что если вы это сделаете, вы должны сопровождать его комментарием, потому что это немного противоречит интуиции, что вы определяете конструктор для предотвращения создания экземпляра класса.
Создание абстрактного служебного класса это не очень хорошая идея, потому что из-за этого класс выглядит так, как будто он предназначен для расширения, и, кроме того, вы можете расширить класс и тем самым создать его экземпляр.