Как вызвать один конструктор из другого в Java? (this() и super())
Использование this() для вызова конструктора того же класса
В Java для вызова одного конструктора из другого в том же классе используется ключевое слово this(). Это называется явным вызовом конструктора. Он должен быть первой инструкцией в конструкторе. Вот как исправить ваш пример:
public class Car {
String brand;
String model;
int year;
String color;
// Главный конструктор
public Car(String brand, String model, int year, String color) {
this.brand = brand;
this.model = model;
this.year = year;
this.color = color;
}
// Конструктор с двумя параметрами
public Car(String brand, String model) {
// Вызываем главный конструктор со значениями по умолчанию
this(brand, model, 2020, "Black");
}
// Конструктор без параметров
public Car() {
// Вызываем конструктор с двумя параметрами, передавая "Unknown"
this("Unknown", "Unknown");
}
}
Теперь при создании объекта new Car("Toyota", "Camry") сначала выполняется вызов this("Toyota", "Camry", 2020, "Black"), который инициализирует все поля. Это избавляет от дублирования кода.
Правила использования this()
- Вызов
this()обязательно должен быть первой строкой в конструкторе. - Нельзя вызывать
this()дважды в одном конструкторе. - Нельзя вызывать
this()иsuper()одновременно (см. ниже). - Цепочка вызовов не должна быть циклической (например, конструктор А вызывает B, а B вызывает A — компилятор выдаст ошибку).
Вызов конструктора родительского класса с помощью super()
Если вы работаете с наследованием, для вызова конструктора суперкласса используется super(). Например:
class Vehicle {
String type;
public Vehicle(String type) {
this.type = type;
}
}
class Car extends Vehicle {
String model;
public Car(String type, String model) {
super(type); // Вызов конструктора Vehicle
this.model = model;
}
}
Без явного вызова super() компилятор автоматически вставит super() (без аргументов), но если в родительском классе нет конструктора по умолчанию, это вызовет ошибку компиляции.
Почему это важно?
- Избежание дублирования: Не нужно повторять код инициализации полей.
- Поддержка: Если изменится логика инициализации (например, добавится новое поле), достаточно изменить только главный конструктор.
- Читаемость: Код становится понятнее — сразу видно, какие конструкторы делегируют работу другим.
Надеюсь, теперь стало ясно! Используйте this() для перегрузки конструкторов в одном классе и super() для вызова конструктора родителя.
Альтернативный подход: фабричные методы и Builder
Хотя this() и super() — стандартное решение, иногда лучше использовать другие паттерны, особенно если у класса много параметров или сложная логика создания.
1. Статические фабричные методы
public class Car {
private String brand;
private String model;
private int year;
private String color;
private Car(String brand, String model, int year, String color) {
this.brand = brand;
this.model = model;
this.year = year;
this.color = color;
}
public static Car createWithDefaults(String brand, String model) {
return new Car(brand, model, 2020, "Black");
}
public static Car createEmpty() {
return new Car("Unknown", "Unknown", 2020, "White");
}
}
Преимущество: можно давать методам осмысленные имена (например, createSportCar()), а конструктор сделать приватным, чтобы контролировать создание объектов.
2. Паттерн Builder
Для классов с большим количеством полей (более 4–5) Builder часто удобнее цепочек конструкторов:
Car car = new Car.Builder()
.brand("Toyota")
.model("Camry")
.year(2023)
.color("Red")
.build();
Builder решает проблему "телескопических конструкторов", когда количество перегрузок растёт экспоненциально. Однако для простых случаев (2–3 конструктора) this() остаётся самым лаконичным и идиоматичным решением.
Выбирайте подход под задачу: для учебных примеров и небольших классов — this(), для production-кода с множеством опций — Builder или фабричные методы.
Ответов пока нет.
Войдите чтобы оставить ответ