Menu

Конструкторы в Java: инициализация объектов с помощью new

Как работают конструкторы в Java: конструктор по умолчанию, параметризованные конструкторы, this, перегрузка конструкторов и цепочки вызовов с this() и super().

На этой странице есть исполняемые редакторы: меняйте, запускайте и сразу видите результат.

Зачем нужны конструкторы

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

Конструктор выглядит как метод, но с двумя отличиями: у него то же имя, что и у класса, и нет типа возвращаемого значения — даже void.

new Point(3, 4) выделяет память под объект, а затем выполняет тело конструктора с x = 3 и y = 4. К моменту, когда new возвращает результат, объект p полностью инициализирован.

Ключевое слово this

В конструкторе выше параметры названы x и y — так же, как поля. this.x означает «поле x, принадлежащее этому объекту», тогда как просто x ссылается на параметр. Без this выражение x = x лишь присвоило бы параметр самому себе и оставило бы поле нетронутым.

this необходим только тогда, когда параметр затеняет поле, но многие используют его повсюду ради ясности. Распространённая ошибка — забыть его при совпадении имён: код компилируется, запускается и молча оставляет ваши поля в значениях по умолчанию (null, 0, false).

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

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

Подвох: как только вы пишете любой конструктор, бесплатный исчезает.

class Box {
    int size;

    Box(int size) {       // теперь конструктора без аргументов НЕТ
        this.size = size;
    }
}

new Box();   // ошибка компиляции: конструктор Box() не существует

Если вы всё же хотите, чтобы new Box() работал, объявите конструктор без аргументов самостоятельно:

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

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

Java выбирает подходящий конструктор по количеству и типам аргументов, которые вы передаёте в new.

Цепочки вызовов с this()

Обратите внимание на дублирование выше: каждый конструктор присваивает поля сам. Этого можно избежать, заставив один конструктор вызывать другой через this(...). Этот вызов должен быть первым оператором в конструкторе.

Теперь сама инициализация находится в одном месте. Меньшие конструкторы лишь подставляют значения по умолчанию и передают работу дальше. Если вы когда-нибудь попытаетесь поставить оператор перед this(...), компилятор его отвергнет.

Конструкторы и super()

Каждый конструктор сначала неявно вызывает конструктор своего суперкласса. Если вы ничего не пишете, Java вставляет скрытый super() (конструктор суперкласса без аргументов) в начало тела. Вы будете работать с этим напрямую, как только начнёте создавать подклассы, — это следующая тема.

class Animal {
    String name;
    Animal(String name) { this.name = name; }
}

class Dog extends Animal {
    Dog(String name) {
        super(name);   // здесь нужно явно вызвать конструктор родителя
    }
}

Поскольку у Animal нет конструктора без аргументов, Dog обязан явно вызвать super(name) — нет бесплатного super(), на который можно положиться. Как и this(), вызов super(...) должен быть первым оператором в конструкторе.

Далее: Наследование

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

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

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

Конструктор — это специальный метод, который выполняется при создании объекта с помощью new. Он имеет то же имя, что и класс, и не имеет типа возвращаемого значения (даже void). Его задача — привести новый объект в корректное начальное состояние, обычно присваивая аргументы конструктора полям объекта.

В чём разница между конструктором и методом в Java?

Конструктор имеет точно такое же имя, как класс, не объявляет тип возвращаемого значения и может быть вызван только через new при создании объекта. У обычного метода своё имя, он объявляет тип возвращаемого значения (или void) и вызывается на уже существующем объекте. Конструкторы инициализируют; методы выполняют работу после этого.

Что произойдёт, если я не напишу конструктор в Java?

Компилятор бесплатно предоставит вам конструктор по умолчанию без аргументов, который не принимает параметров и не делает ничего, кроме неявного вызова super(). Но как только вы сами напишете любой конструктор, этот бесплатный исчезает: поэтому, если вы добавите параметризованный конструктор и при этом хотите, чтобы new Thing() по-прежнему работал, вам нужно явно объявить конструктор без аргументов.

Coddy programming languages illustration

Учитесь программировать с Coddy

НАЧАТЬ