Создание объекта. Порядок вызова конструкторов

Открыта

— Привет, Амиго! Сейчас я расскажу тебе о процессе создания объекта.

— А что там сложного, дядя Риша? Написал new имя класса, указал правильный конструктор и готово!

— Это так. Но что при этом происходит внутри объекта?

— А что там происходит?

— А вот что! Объект создается в несколько этапов.

1) Сначала выделяется память под все переменные – поля класса.

2) Затем идет инициализация базового класса.

3) Потом всем переменным присваиваются значения, если они указаны.

4) И наконец, вызывается конструктор.

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

— Давай посмотрим, как это будет работать на примере двух классов:

Код Описание
class Pet
{
 int x = 5, y = 5;-
 int weight = 10;-

 Pet(int x, int y)
 {
  this.x = x;-
  this.y = y;-
 }
}
class Cat extends Pet
{
 int tailLength = 8;-
 int age;
 Cat(int x, int y, int age)
 {
  super(x, y);-
  this.age = age;-
 }
}
Мы создали два класса: Pet(животное) и Cat(кот).

В классе Cat мы видим явный вызов конструктора базового класса.
Он всегда должен быть в первой строке конструктора.

Вот что произойдет после выделения памяти:
18 – вызов конструктора базового класса
3, 4 – инициализация переменных в Pet
8, 9 – отработает код конструктора Pet

далее начнется процесс инициализации класса Cat
14 – инициализация переменных в Cat
19 – отработает код конструктора Cat

public static void main(String[] args)
{
 Cat cat = new Cat (50, 50, 5);
}

— Что-то немного запутанно. Почему так сложно?

— На самом деле не сложно, если знать что на самом деле происходит:
Если у класса нет ни одного конструктора, он будет создан автоматически.

Конструктор по умолчанию
class Cat
{
 int x = 5;
 int y = 5;
}
class Cat
{
 int x = 5;
 int y = 5;
 public Cat()
 {
 }
}

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

Вызов конструктора базового класса
class Pet
{
 public String name;
}
class Pet extends Object
{
 public String name;
 public Pet()
 {
  super();
 }
}
class Cat extends Pet
{
 int x = 5;
 int y = 5;
}
class Cat extends Pet
{
 int x = 5;
 int y = 5;
 public Cat()
 {
  super();
 }
}

Инициализация переменных класса происходит в конструкторе.

Инициализация переменных класса
class Cat
{
 int x = 5;
 int y = 5;
}
class Cat
{
 int x;
 int y;
 public Cat()
 {
  super();
  this.x = 5;
  this.y = 5;
 }
}
Как все это происходит на самом деле
class Pet
{
 int x = 5, y = 5;
 int weight = 10;
 Pet(int x, int y)
 {
  this.x = x;
  this.y = y;
 }
}

class Cat extends Pet
{
 int tailLength = 8;
 int age;
 Cat(int x, int y, int age)
 {
  super(x, y);
  this.age = age;
 }
}
class Pet extends Object
{
 int x;
 int y;
 int weight;

 Pet(int x, int y)
 {
  //вызов конструктора базового класса
  super();
  //инициализация переменных
  this.x = 5;
  this.y = 5;
  this.weight = 10;
  //вызов кода конструктора
  this.x = x;
  this.y = y;
 }
}
class Cat extends Pet
{
 int tailLength;
 int age;
 Cat(int x, int y, int age)
 {
  //вызов конструктора базового класса
  super(x, y);
  //инициализация переменных
  this.tailLength = 8;
  //вызов кода конструктора
  this.age = age;
 }
}
4
Задача
Java Core,  5 уровень,  5 лекция
Недоступна
Набираем код Ӏ Java Core: 5 уровень, 5 лекция
Иногда думать не надо, строчить надо! Как ни парадоксально звучит, порой пальцы «запоминают» лучше, чем сознание. И даже на втором квесте иногда полезно просто понабирать код. Вперёд!

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

— Молодец, Амиго, именно так!

Комментарии (148)
  • популярные
  • новые
  • старые
Для того, чтобы оставить комментарий вы должны авторизоваться
baddan 15 уровень, Тамбов
вчера, 06:00
работа абстрактных классов отличаются или нет от обычных?
🦔 Виктор админ Java Android канала в telegram @LetsCodeItExpert
10 января, 03:41
Вспоминаем порядок инициализации переменных и конструкторов: 1. Инициализируются статические переменные базового класса. 2. Статический блок инициализации базового класса. 3. Инициализируются статические переменные дочернего класса. 4. Статический блок инициализации дочернего класса. 5. Инициализируются нестатические переменные базового класса. 6. Нестатический блок инициализации базового класса. 7. Начинает работу конструктор базового класса. 8. Инициализируются нестатические переменные дочернего класса. 9. Нестатический блок инициализации базового класса. 10. Начинает работу конструктор дочернего класса. 11. Всё получится! -- tlgrm: @LetsCodeIt | @SefoNotasi
Александр Долженко 16 уровень, Лондон
19 января, 22:17
Забыли статитические и нестатические блоки инициализации.
🦔 Виктор админ Java Android канала в telegram @LetsCodeItExpert
20 января, 12:16
Спасибо, добавил.
stepa113 15 уровень, Москва
вчера, 13:41
А что такое статический/нестатический блок инициализации?
🦔 Виктор админ Java Android канала в telegram @LetsCodeItExpert
вчера, 17:16
Очень ёмкая и доступная статья про блоки инициализации в Java на Vertex Academy.
Jerry QA Automation Engineer
5 января, 11:11
Может кто то из опытных пояснит такой момент. Если у нашего класса нет родителя, мы создаем его обьект, вызывается super() класса Object. А если мы создаем обьект самого класса Object, то чей super() вызывается у него? Или же не вызывается 🤔
Veygard 20 уровень, Москва
22 декабря 2020, 14:49
Алгоритм:
Alec I 16 уровень
21 декабря 2020, 03:25
познавательно, но зачем мне все это надо? как я могу использовать данную информацию? Польза в том, что конструктор родителя надо всегда писать первым. Про остальную логику или последовательность, пока не понятно, как я могу это использовать при написании кода.
Veygard 20 уровень, Москва
22 декабря 2020, 14:21
Надо помнить, что при создании нового объекта (Cat cat = new Cat();) - сначало идёт выполнение кода в конструкторе класса родителя. Вот другой пример: Т.е. тут сначала напечаталось в консоле запись до создания объекта, потом надпись в конструкторе родителя, потом в классе объект которого был создан. Как это может пригодиться: К примеру в логике твоей программы, каждый объект животного, который ты создаешь должен выполнить какой-то метод. Например, doRoar(); - который будет условно кричать при рождении. Ты можешь в каждом конструкторе каждого типа животного (Cat, Dog и т.д.) прописывать вызов этого метода. А можешь прописать его только в конструкторе класса родителя - и он будет вызваться для любого наследника. Короче уменьшаем кол-во строчек кода для написания.
Гордей 28 уровень
21 ноября 2020, 11:02
Может если кто не знал, то в этих задачах с набиранием кода можно копировать. Хоть там явно и не подсвечивается, но текст выделяется. Далее Ctrl+C Ctrl+V
Dmitry Gebeydullov дибилопер
22 ноября 2020, 17:48
сначала Ctrl+A и т.д.
Ярослав Степанов 17 уровень, Санкт-Петербург
24 августа 2020, 16:40
У меня одного нумерация поехала? Version 84.0.4147.135 (Official Build) (64-bit) Display 1920*1080 Windows zoom factor 150%
Алексей 16 уровень, Москва
27 августа 2020, 21:23
Ты не один, у меня тоже так
Pig Man Главная свинья в Свинарнике
25 октября 2020, 10:10
Светлая тема, как непривычно. И да, на темной стороне такие же проблемы
Romul Java Developer в Роскосмос
10 августа 2020, 14:01
Вначале инициализируются статические переменные базового класса, затем класса-потомка. Вот хорошее видео на подробный разбор этапов создания объекта - https://www.youtube.com/watch?v=cla2N9B88rs
Иван Full Stack Developer
8 августа 2020, 18:06
То чувство, когда объяснение очевидно и ты просто берёшь и копируешь код из примера в задачку.
Станислав 19 уровень, Москва
19 октября 2020, 16:55
return super.Иван
dolcom 22 уровень, Самара
29 июля 2020, 09:14
3) Потом всем переменным присваиваются значения, если они указаны.

4) И наконец, вызывается конструктор.
Исходя из блоков "Как всё происходит на самом деле", вероятнее всего порядок должен быть такием:
3) Потом вызывается конструктор.

4) И, наконец, в конструкторе всем переменным присваиваются значения, если они указаны.
В противном случае, непонятно для чего вызывается конструктор, если переменные и без него инициализируются
Evgeny Siganov 22 уровень, Москва
4 октября 2020, 15:49
1) Инициализация статических переменных родительского класса 2) Инициализация статических переменных дочернего класса 3) Инициализация нестатических переменных родительского класса 4) Вызывается конструктор родительского класса 5) Инициализация нестатических переменных дочернего класса 6) Вызывается конструктор дочернего класса вот такой вот порядок в Java