ООП ·
‹ Предыдущий Следующий ›
⏱ 5 минут чтения Обновлено: 2026-07-25

Виды конструкторов в Java

1. Что такое конструктор в Java

Конструктор в Java — это специальный блок кода, который выполняется при создании объекта и приводит его в корректное начальное состояние. Всё, что записано после ключевого слова new, — это и есть вызов конструктора:

Box myBox = new Box();

У конструктора три отличительных признака:

  • его имя точно совпадает с именем класса;
  • у него нет возвращаемого типа — даже void писать нельзя;
  • он вызывается только через new (либо из другого конструктора через this()/super()), напрямую по имени его вызвать невозможно.

Добавим конструктор в класс Box сразу после переменных. Синтаксис похож на метод, но без типа результата. Внутри конструктора мы задаём полям значение 10:

public class Box {
    double width;
    double height;
    double depth;

    Box() {
        System.out.println("Конструирование объекта Box");
        width = 10;
        height = 10;
        depth = 10;
    }

    /**
     * Подсчитать объём коробки
     *
     * @return объём
     */
    double getVolume() {
        return width * height * depth;
    }
}

Теперь каждый вызов new Box() запускает этот код: создаются два объекта, и оба сразу получают размеры 10 × 10 × 10.

public class BoxExample3 {
    public static void main(String[] args) {
        Box myBox1 = new Box();
        Box myBox2 = new Box();

        System.out.println("Объём: " + myBox1.getVolume());
        System.out.println("Объём: " + myBox2.getVolume());
    }
}
Конструирование объекта Box
Конструирование объекта Box
Объём: 1000.0
Объём: 1000.0

2. Конструктор по умолчанию

Первые примеры класса Box вообще не содержали конструктора, но объекты создавались. Причина в том, что если в классе не объявлен ни один конструктор, компилятор добавляет его сам — это и есть конструктор по умолчанию (default constructor). Он не принимает параметров, имеет тот же модификатор доступа, что и класс, а его тело состоит из единственного неявного вызова конструктора суперкласса:

public class Box {
    double width;
    double height;
    double depth;

    // Этот конструктор компилятор дописывает сам,
    // если в классе нет ни одного конструктора
    Box() {
        super(); // неявный вызов конструктора Object
    }
}

Как только вы объявите хотя бы один собственный конструктор — с параметрами или без, — конструктор по умолчанию больше не генерируется. Именно поэтому после добавления Box(double w, double h, double d) строка new Box() перестаёт компилироваться.

Важное уточнение

Часто пишут, что «конструктор по умолчанию заполняет поля значениями по умолчанию». Это не так: нули, false и null полям присваивает JVM при выделении памяти под объект — ещё до выполнения любого кода конструктора. Сам сгенерированный конструктор пуст. Различайте также конструктор по умолчанию (создан компилятором) и конструктор без параметров (написан вами) — на собеседовании это разные вещи.

3. Конструктор с параметрами

Конструктор, как и метод, может принимать аргументы. Такие конструкторы называют параметризованными. Они позволяют создать объект сразу в нужном состоянии, без последовательности вызовов сеттеров.

Объявим конструктор, который принимает три значения и инициализирует ими поля класса:

public class Box {
    double width;
    double height;
    double depth;

    /**
     * Конструктор класса Box
     *
     * @param w ширина
     * @param h высота
     * @param d глубина
     */
    Box(double w, double h, double d) {
        width = w;
        height = h;
        depth = d;
    }

    /**
     * Подсчитать объём коробки
     *
     * @return объём
     */
    double getVolume() {
        return width * height * depth;
    }
}

Теперь создание объектов выглядит так. Закомментированная строка не скомпилируется: собственный конструктор объявлен, значит конструктора без параметров у класса больше нет.

public class BoxExample4 {
    public static void main(String[] args) {
        Box myBox1 = new Box(10, 20, 15);
        Box myBox2 = new Box(3, 6, 9);
        // Box myBox3 = new Box(); // ошибка компиляции:
        // constructor Box in class Box cannot be applied to given types

        System.out.println("Объём: " + myBox1.getVolume());
        System.out.println("Объём: " + myBox2.getVolume());
    }
}

4. Перегрузка конструкторов

Чтобы вернуть возможность писать new Box(), достаточно добавить в класс ещё один конструктор. Несколько конструкторов с разными списками параметров — это перегрузка. Более подробно о перегрузке в уроке перегрузка методов и конструкторов.

5. Вызовы this() и super()

Из конструктора можно вызвать другой конструктор: this(...) — конструктор этого же класса, super(...) — конструктор суперкласса. Такой вызов возможен только первым оператором конструктора, а this(...) и super(...) нельзя использовать одновременно. Подробный разбор синтаксиса, правил и частых ошибок — в отдельных уроках о ключевом слове this и ключевом слове super.

6. Конструктор и метод: в чём разница

Внешне конструктор похож на метод, но ведёт себя иначе. Сводная таблица отличий:

Признак Конструктор Метод
Имя Строго совпадает с именем класса Любое допустимое имя
Возвращаемый тип Отсутствует, даже void писать нельзя Обязателен: тип или void
Вызов Только через new, this(...), super(...) По имени, сколько угодно раз
Наследование Не наследуется и не переопределяется Наследуется, может быть переопределён
Если не написан Компилятор добавит конструктор по умолчанию Ничего не добавляется
Модификаторы public, protected, private или без модификатора Дополнительно static, final, abstract, synchronized

Конструктор нельзя объявить static, final, abstract или native: он не участвует в полиморфизме и всегда работает с конкретным создаваемым экземпляром.

7. На чём чаще всего ошибаются

  • Случайно превратили конструктор в метод. Стоит написать void Box() { ... } — и код скомпилируется, но это уже обычный метод с именем Box. Объект будет создаваться сгенерированным конструктором по умолчанию, а ваш код молча не выполнится. Ошибка коварна именно тем, что компилятор не возражает.
  • Вызов переопределяемого метода из конструктора. Конструктор суперкласса отрабатывает раньше полей подкласса, поэтому переопределённый метод увидит ещё не инициализированные поля наследника (нули и null). Из конструктора безопасно вызывать только private, static и final методы.
  • Тяжёлая логика в конструкторе. Задача конструктора — довести объект до валидного состояния. Обращения к базе, чтение файлов и запуск потоков лучше вынести наружу или в статический фабричный метод: недостроенный объект, вылетевший с исключением, отладить трудно.
  • Ожидание, что конструктор наследуется. Конструкторы родителя не появляются в подклассе автоматически — нужные варианты объявляют заново и делегируют через super(...).

Отдельно отметим современную альтернативу: если класс нужен только для хранения данных, вместо ручного написания конструктора, equals() и hashCode() используйте record (Java 16+). Канонический конструктор компилятор сгенерирует сам, а проверку аргументов можно добавить в компактном конструкторе:

public record Box(double width, double height, double depth) {
    // компактный конструктор: только валидация
    public Box {
        if (width <= 0 || height <= 0 || depth <= 0) {
            throw new IllegalArgumentException("Размеры должны быть положительными");
        }
    }

    double getVolume() {
        return width * height * depth;
    }
}

Часто задаваемые вопросы

Может ли конструктор возвращать значение?

Нет. У конструктора нет возвращаемого типа, и указывать void тоже нельзя. Если написать void Box() { }, компилятор воспримет это как обычный метод с именем Box: код скомпилируется, но при new Box() он вызван не будет. Это классический вопрос на собеседовании.

Чем конструктор по умолчанию отличается от конструктора без параметров?

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

Зачем нужен приватный конструктор?

Приватный конструктор запрещает создавать объекты извне класса. Его применяют в утилитных классах со статическими методами, в синглтоне, а также когда объекты выдаются через статические фабричные методы с говорящими именами, например Box.ofCube(7).

Может ли конструктор выбрасывать исключение?

Да, конструктор может объявлять throws и бросать любые исключения. Это штатный способ не допустить создание объекта с некорректными данными: проверьте аргументы и бросьте IllegalArgumentException. Ссылка на объект вызывающему коду в этом случае не вернётся.

Подробнее см. официальную документацию Oracle.

Видео объяснение

Предпочитаете видеоформат? Посмотрите этот урок с примерами и объяснениями.

Комментарии

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