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

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

1. Что такое ключевое слово this

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

Фактически обращение к полю width внутри метода — это сокращённая запись this.width. Обе строки ниже делают одно и то же:

public class Box {
    double width;

    void printWidth() {
        System.out.println(width);      // неявно: this.width
        System.out.println(this.width); // явно
    }
}

Раз запись эквивалентна, возникает вопрос: зачем тогда this вообще нужен? Есть четыре ситуации, где без него не обойтись:

  • параметр метода или конструктора перекрывает поле с тем же именем;
  • нужно вызвать другой конструктор этого же класса — this(...);
  • нужно передать сам объект в другой метод или сохранить его где-то;
  • нужно вернуть текущий объект, чтобы строить цепочки вызовов.

Важно

this существует только у объекта. В static-методе, статическом блоке инициализации и в main ключевого слова this нет: компилятор выдаст ошибку non-static variable this cannot be referenced from a static context.

2. Конфликт имён: поле и параметр называются одинаково

Самый частый случай — конструктор или сеттер, у которого параметры названы так же, как поля класса. Внутри такого метода имя width относится к параметру: локальная переменная перекрывает (затеняет) поле класса. Чтобы добраться до поля, используют this:

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

    Box(double width, double height, double depth) {
        this.width = width;   // слева — поле объекта, справа — параметр
        this.height = height;
        this.depth = depth;
    }

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

Если назвать параметры по-другому, затенения не будет и this станет не нужен — компилятор и так понимает, где поле, а где параметр:

Box(double w, double h, double d) {
    width = w;
    height = h;
    depth = d;
}

На практике первый вариант предпочтительнее: имена параметров совпадают с именами полей, читать такой конструктор проще, а IDE и генераторы кода (в том числе Alt+Insert в IntelliJ IDEA) создают сеттеры именно в таком стиле.

3. Вызов конструктора через this()

Вторая роль ключевого слова — форма this(...). С её помощью один конструктор вызывает другой конструктор этого же класса. Это приём против дублирования кода: вся логика инициализации живёт в одном «главном» конструкторе, а остальные подставляют значения по умолчанию и делегируют работу ему. Такой приём называют цепочкой конструкторов (constructor chaining), и он тесно связан с перегрузкой.

public class Toy {
    String name;
    int cost;
    String manufacturer;
    int age;

    public Toy(String name, int cost, String manufacturer, int age) {
        this(name, cost, manufacturer);
        this.age = age;
        System.out.println("В конструкторе с четырьмя параметрами");
    }

    public Toy(String name, int cost, String manufacturer) {
        this();
        this.name = name;
        this.cost = cost;
        this.manufacturer = manufacturer;
        System.out.println("В конструкторе с тремя параметрами");
    }

    public Toy() {
        System.out.println("В конструкторе по умолчанию");
    }
}
public class ToyExample {
    public static void main(String[] args) {
        Toy toy = new Toy("Кукла", 34, "Disney", 3);
    }
}

Результат программы:

В конструкторе по умолчанию
В конструкторе с тремя параметрами
В конструкторе с четырьмя параметрами

Вывод показывает главное: сначала до конца отрабатывает вызванный конструктор и только потом продолжается тело вызывающего. Цепочка раскручивается «вглубь», а печать идёт в обратном порядке.

Правила, которые нужно помнить:

  • вызов this(...) должен быть первой инструкцией конструктора (об исключении из этого правила — в заметке ниже);
  • в одном конструкторе нельзя одновременно вызвать this(...) и super(...);
  • цепочка не может замкнуться: конструктор, который прямо или косвенно вызывает сам себя, не компилируется — recursive constructor invocation;
  • this(...) можно писать только внутри конструктора; из обычного метода вызвать конструктор нельзя.

Что изменилось в современной Java

Формулировка «this() обязан быть первой строкой» верна для Java 8–21. Начиная с Java 25 действуют гибкие тела конструкторов (JEP 513): перед this(...) или super(...) разрешены инструкции пролога — проверка аргументов, вычисление значений. Ограничение осталось одно: до явного вызова конструктора нельзя обращаться к создаваемому экземпляру, то есть читать и писать поля через this. Для собеседований и учебного кода безопаснее придерживаться классического правила.

4. Другие применения this

Передача текущего объекта

Ссылку this можно передать как обычный аргумент — например, зарегистрировать объект в другом классе:

public class Button {
    private final EventBus bus;

    public Button(EventBus bus) {
        this.bus = bus;
    }

    public void register() {
        bus.subscribe(this); // передаём саму кнопку
    }
}

Возврат this и цепочки вызовов

Если метод возвращает this, вызовы можно объединять в цепочку. На этом построены билдеры и «текучие» (fluent) API:

public class Pizza {
    private String size;
    private boolean cheese;

    public Pizza size(String size) {
        this.size = size;
        return this;
    }

    public Pizza cheese(boolean cheese) {
        this.cheese = cheese;
        return this;
    }

    @Override
    public String toString() {
        return "Pizza{size=" + size + ", cheese=" + cheese + "}";
    }
}
Pizza pizza = new Pizza()
        .size("L")
        .cheese(true);
System.out.println(pizza); // Pizza{size=L, cheese=true}

5. this и this(): сравнение

Эти две конструкции легко перепутать на собеседовании. Разница между ними такая:

Конструкция Что это Где можно использовать Типичное применение
this Ссылка на текущий объект В любом нестатическом методе и конструкторе this.width = width, передача и возврат объекта
this(...) Вызов другого конструктора этого же класса Только в конструкторе, первой инструкцией Цепочка конструкторов, значения по умолчанию

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

  • Забытый this в сеттере. Строка width = width; компилируется без ошибок, но присваивает параметр самому себе — поле остаётся равным 0.0. Ошибка проявится только во время работы программы. IDE подсвечивает такие строки предупреждением, не игнорируйте его.
  • this в статическом контексте. В main и любом static-методе объекта нет, поэтому обращение к this — ошибка компиляции.
  • Замкнутая цепочка конструкторов. Если A() вызывает A(int), а тот снова A(), код не соберётся: компилятор поймает рекурсию сразу, до запуска.
  • Попытка совместить this(...) и super(...). Разрешён только один явный вызов конструктора.
  • Публикация this из конструктора (this escape). Если передать this наружу до окончания конструктора (зарегистрировать слушателя, положить в статическую коллекцию, запустить поток), другой код увидит объект с недоинициализированными полями, в том числе final. Регистрацию выносят в отдельный метод или фабричный метод.

Формальные правила по this и по вызовам конструкторов описаны в спецификации языка: JLS, раздел 8.8.7 Constructor Body.

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

Обязательно ли писать this перед полями класса?

Нет. Если локальная переменная или параметр не перекрывает поле, компилятор сам подставляет this, и запись width эквивалентна this.width. Явный this обязателен только там, где имя затенено — обычно в конструкторах и сеттерах, где параметр назван так же, как поле.

Можно ли поставить this() не первой строкой конструктора?

В Java 8-21 нет: компилятор выдаст ошибку call to this must be first statement in constructor. Начиная с Java 25 гибкие тела конструкторов (JEP 513) разрешают инструкции до this(...) и super(...), например проверку аргументов, но обращаться к полям создаваемого объекта в этом прологе по-прежнему нельзя.

На что указывает this внутри лямбда-выражения?

На объект внешнего класса, в котором лямбда объявлена: у лямбды нет собственного this. У анонимного класса поведение другое — там this ссылается на сам экземпляр анонимного класса, а не на объект, в котором он создан.

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

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

Комментарии

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