JС: Жизненный цикл создания java объектов

В этой статье я расскажу про то, через какие этапы проходит java объекты при их создании. Другими словами, я расскажу про жизненный цикл java объектов.

Для начинающего java разработчика очень важно понимание жизненного цикла класса. Это поможет быстро решать возникшие ошибки компиляции и предотвратит появление многочисленных багов.

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

Пример 1

Например, мы имеем следующий код в файле Main.java.

При выполнение метода main мы увидим следующий текст.

Как Вы видите java без надобности не подгружает классы, которые не используются. Я говорю о классах ObjectCircle и ParentObjectCircle. Загрузчик классов (класс ClassLoader) не начнет их загружать в память без надобности.

Пример 2

Теперь давайте этот файл немного изменим. И добавим в метод main создание объекта класса ObjectCircle. Остальной файл Main.java остался без изменений.

Данный код выведет следующий текст в консоль.

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

Теперь в консоль выведется следующий текст.

Обратите внимание на то, что статический блок выполняется только один раз. Это происходит потому, что статические блоки кода выполняются при загрузке класса ClassLoader-ом в память. Когда мы создаем второй объект, этого не происходит т.к. этот класс уже был загружен в память при создании первого объекта. Еще обратите внимание на то, что перед выполнением статического блока первым делом проинициализировались все статические переменные этого класса, а уже потом выполнился статический блок кода. Об этом говорит то, что в консоли первым появился следующий текст.

После того как класс был загружен, выполнилась инициализация статических переменных и выполнились статические блоки кода происходит непосредственное создание объекта данного класса. А именно в первую очередь инициализируются не статические переменные, за ними идет выполнение не статического блока кода, а затем выполнение конструктора. При следующем создании объекта данного класса выполнятся только эти этапы. Об этом также говорит выведенный в консоль текст.

Последнее о чем стоит сказать это то, что метод finalize вообще не вызвался. Многие новички полагают, что это некоторый аналог деструктора из C++. Но в отличие от C++ java не гарантирует его выполнение. Поэтому его и не рекомендуют использовать.

Пример 3

В следующем примере разберем немного измененный файл Main.java. Сделаем так, чтобы класс ObjectCircle расширял класс ParentObjectCircle.

Выполним снова метод main и посмотрим, что из этого получилось.

Теперь стало все намного сложнее и интереснее. При создании первого объекта класса ObjectCircle ClassLoader загружает не сам этот класс, а в первую очередь в память загружается его родительский класс. И уже в нем выполняется инициализация статических переменных.

А затем выполняются статические блоки.

После чего идет инициализация уже статических переменных нашего класса.

И выполняются статические блоки.

После того как оба класса ClassLoader-ом загружены в память идет создание самих объектов. Обратите внимание на то, что сначала инициализируются не статические поля родительского класса, выполняются не статические блоки кода родительского класса, а уже потом выполняется конструктор родительского класса.

Затем все происходит как в примере без родительских классов. Выполняется инициализация не статических переменных, выполняются не статические блоки кода и на конец выполняется конструктор создаваемого класса.

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

Опять обратите внимание на то, что метод finalize не вызвался!

Пример 4

Рассмотрим еще один уже последний пример на сегодня. Создадим файл ObjectCircle.java.

В этом примере мы полностью избавились от класса Main и метод main перенесли в класс ObjectCircle. Посмотрим, что выведется на экран, если мы запустим метод main.

Получился очень интересны результат. Выходит, что из-за того, что мы метод main перенесли в сам класса ObjectCircle, ClassLoader намного раньше загрузил в память классы ObjectCircle и ParentObjectCircle. Это конечно же объясняется тем, что метод main находится в классе ObjectCircle и для выполнения метода main его нужно загрузить. Но для загрузки класса ObjectCircle  нужно предварительно загрузить в память еще и класс ParentObjectCircle. Поэтому произошла инициализация статических полей и статических блоков кода в этих классах еще до выполнения метода main.

Настало время подвести итог.

При первом упоминании классов в приложении, java используя класс ClassLoader загружает необходимый класс в память и после этого начинает инициализацию статических переменных, а затем выполняются статические блоки кода. Но, если данный класс является потомком какого-то другого класса, то ClassLoader сначала проделает все те же этапы для родительских классов, а уже затем для того которого нужно.

После того как все необходимые этапы при загрузке классов в память пройдены, происходит создание объектов данного класса. Но оно начинается не с выполнения конструктора, а с инициализации сначала не статических переменных и затем выполнения не статических блоков кода. А уже потом выполняется конструктор.

Переопределении метода finalize может приводить к проблемам связанным с некорректным освобождением ресурсов. Это связано с тем, что нет никакой гарантии, что метод finalize будет вызван. Используйте его только, если на все 100% знаете к чему это приведет.

Добавить комментарий

Ваш e-mail не будет опубликован.

*

Можно использовать следующие HTML-теги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">