1. Введение
Частные конструкторы позволяют ограничить создание экземпляров класса . Проще говоря, они предотвращают создание экземпляров класса в любом месте, кроме самого класса.
Публичные и частные конструкторы, используемые вместе, позволяют контролировать то, как мы хотим создавать экземпляры наших классов — это известно как делегирование конструктора.
2. Типичное использование
Существует несколько шаблонов и преимуществ ограничения явного создания экземпляров классов, и в этом руководстве мы рассмотрим наиболее распространенные из них:
Давайте посмотрим, как определить частный конструктор :
public class PrivateConstructorClass {
private PrivateConstructorClass() {
// in the private constructor
}
}
Мы определяем частные конструкторы аналогично общедоступным конструкторам; мы просто изменили ключевое слово public
на private
.
3. Использование приватных конструкторов в шаблоне Singleton
Одноэлементный шаблон — одно из наиболее распространенных мест, где мы сталкиваемся с использованием закрытого конструктора. Частный конструктор позволяет нам ограничить создание экземпляра класса одним экземпляром объекта :
public final class SingletonClass {
private static SingletonClass INSTANCE;
private String info = "Initial info class";
private SingletonClass() {
}
public static SingletonClass getInstance() {
if (INSTANCE == null) {
INSTANCE = new SingletonClass();
}
return INSTANCE;
}
// getters and setters
}
Мы можем создать экземпляр, вызвав SingletonClass.getInstance()
— это либо возвращает существующий экземпляр, либо создает его, если это первый экземпляр. Мы можем создать экземпляр этого класса только с помощью статического метода getInstance() .
4. Использование приватных конструкторов для делегирования конструкторов
Другим распространенным вариантом использования частных конструкторов является предоставление средства делегирования конструктора. Делегирование конструктора позволяет нам передавать параметры через несколько различных конструкторов, ограничивая инициализацию определенными местами .
В этом примере ValueTypeClass
допускает инициализацию со значением и типом, но мы хотим разрешить это только для подмножества типов. Общий конструктор должен быть закрытым, чтобы гарантировать использование только разрешенных типов:
public class ValueTypeClass {
private final String value;
private final String type;
public ValueTypeClass(int x) {
this(Integer.toString(x), "int");
}
public ValueTypeClass(boolean x) {
this(Boolean.toString(x), "boolean");
}
private ValueTypeClass(String value, String type) {
this.value = value;
this.type = type;
}
// getters and setters
}
Мы можем инициализировать класс
ValueType
с помощью двух разных общедоступных конструкторов: один принимает int
, а другой — boolean
. Затем каждый из этих конструкторов вызывает общий закрытый конструктор для завершения инициализации объекта.
``
5. Использование приватных конструкторов для создания нереализуемых классов
Неинстанцируемые классы — это классы, экземпляры которых мы не можем создать. В этом примере мы создадим класс, который просто содержит набор статических методов :
public class StringUtils {
private StringUtils() {
// this class cannot be instantiated
}
public static String toUpperCase(String s) {
return s.toUpperCase();
}
public static String toLowerCase(String s) {
return s.toLowerCase();
}
}
Класс StringUtils
содержит пару статических служебных методов и не может быть создан из-за закрытого конструктора.
На самом деле нет необходимости разрешать создание экземпляра объекта, поскольку статические методы не требуют использования экземпляра объекта.
6. Использование приватных конструкторов в шаблоне Builder
Шаблон построителя позволяет нам создавать сложные объекты шаг за шагом, вместо того, чтобы иметь несколько конструкторов, обеспечивающих различные способы создания объекта. Частный конструктор ограничивает инициализацию, позволяя вместо этого разработчику управлять созданием объекта .
В этом примере мы создали класс Employee , который содержит
имя
, возраст
и отдел
сотрудника:
public class Employee {
private final String name;
private final int age;
private final String department;
private Employee(String name, int age, String department) {
this.name = name;
this.age = age;
this.department = department;
}
}
Как мы видим, мы сделали конструктор Employee
закрытым, поэтому мы не можем создать экземпляр класса явно.
Теперь мы добавим внутренний класс Builder
в класс Employee
:
public static class Builder {
private String name;
private int age;
private String department;
public Builder setName(String name) {
this.name = name;
return this;
}
public Builder setAge(int age) {
this.age = age;
return this;
}
public Builder setDepartment(String department) {
this.department = department;
return this;
}
public Employee build() {
return new Employee(name, age, department);
}
}
Конструктор теперь может создавать разных сотрудников с именем
, возрастом
или отделом
— нет ограничений на количество полей, которые мы должны предоставить:
Employee.Builder emplBuilder = new Employee.Builder();
Employee employee = emplBuilder
.setName("foreach")
.setDepartment("Builder Pattern")
.build();
Мы создали сотрудника
с именем « foreach
» и отделом « Builder Pattern
». Возраст не указан, поэтому будет использоваться примитивное значение int
по умолчанию, равное 0.
7. Использование частных конструкторов для предотвращения подклассов
Другое возможное использование частных конструкторов — предотвращение создания подклассов класса. `Если бы мы попытались создать такой подкласс, то не смогли бы вызвать
суперконструктор . Однако важно отметить, ** что обычно мы делаем класс [
final`](/lessons/b/-java-final) для предотвращения создания подклассов, а не для использования частного конструктора** .
8. Заключение
Основное использование приватных конструкторов — ограничение создания экземпляров классов. Частные конструкторы особенно полезны, когда мы хотим ограничить внешнее создание класса .
Одиночки, фабрики и объекты статических методов являются примерами того, как ограничение инстанцирования объектов может быть полезным для обеспечения соблюдения определенного шаблона.
Классы-константы и классы статических методов также диктуют, что класс не должен создавать экземпляры. Важно помнить, что мы также можем комбинировать частные конструкторы с общедоступными конструкторами, чтобы разрешить совместное использование кода внутри различных определений общедоступных конструкторов .
Код этих примеров можно найти на GitHub .