Статический блок инициализации java

Содержание

Блок инициализации (initialization block) — понятие в объектно-ориентированном программировании, в основном известное из языка Java, которое представляет собой последовательность команд, выполняемых при создании (загрузке) классов и объектов. Разработано, чтобы значительно увеличить мощность конструктора. Существуют два типа: статический блок инициализации, обычно называемый для краткости статический блок (static block), и динамический блок инициализации (instance block).

Содержание

Мотивация [ править | править код ]

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

Статический блок инициализации [ править | править код ]

Статический блок — это, в сущности, конструктор для всего класса. Его синтаксис:

Он ставится между определениями полей и функциями класса. Команды будут выполняться в одном из двух случаев, том, который наступит раньше:

  1. При создании первого объекта класса в процессе работы программы, перед запуском конструктора.
  2. При первом вызове статической функции, перед выполнением.

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

Строку 4 можно легко присоединить к строке 2, без необходимости в статическом блоке. Однако строки 5—8 показывают потребность в нём — возможность выполнять сложные команды на уровне класса, которые на уровне объекта появились бы в конструкторе.

Читайте также:  Irobot roomba 800 аккумулятор

Динамический блок инициализации [ править | править код ]

Динамический блок представляет собой дополнение к конструктору. Его синтаксис:

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

Порядок выполнения загрузки [ править | править код ]

При разработке языка Java был установлен постоянный порядок действий при загрузке. Во время загрузки класса порядок выглядит следующим образом:

  1. Определения статических полей родительских классов.
  2. Инициализация статических полей и выполнение статических блоков родительских классов.
  3. Определения статических полей класса.
  4. Инициализация статических полей и выполнение статических блоков класса.

Затем, при создании объекта, порядок выглядит следующим образом:

  1. Определения полей объекта из родительских классов.
  2. Инициализация полей и выполнение динамических блоков из родительских классов.
  3. Выполнение конструкторов из родительских классов.
  4. Определения полей объекта из его класса.
  5. Инициализация полей и выполнение динамических блоков из его класса.
  6. Выполнение конструктора из его класса.

Когда существует цепочка предков, все действия выполняются сначала для самого дальнего предка (класс Object), а затем вниз по цепочке в том же порядке до текущего класса.

При наличии более чем одного типа в одном и том же разделе выше, действия выполняются в порядке появления в программе. Например, следующий код:

присваивает в каждом объекте переменной i значение 30. Но код:

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

Возможные проблемы [ править | править код ]

Использование переменной до её определения [ править | править код ]

Вопреки тому, что можно ожидать, следующий код:

не пройдёт компиляцию в строке 4 на том основании, что правая переменная i была использована, прежде чем она была определена, несмотря на то что строка 3 пройдёт компиляцию и выполнится без проблем, несмотря на то что левая i в строке 4 не вызывает ошибку, и несмотря на то что во время работы при достижении начала строки 4 переменная была определена и получила значение. Это происходит потому, что размещение переменных (например, в строке 3) проверяется по списку переменных, определённых на данный момент в процессе выполнения программы, включая все статические поля, а использование такой переменной проверяется по местоположению определения.

Локальная статическая переменная [ править | править код ]

Вопреки тому, что можно ожидать, следующий код:

не пройдёт компиляцию в строке 6 на том основании, что переменная не определена, потому что определение переменной в статическом блоке не создает статическую переменную, а только локальную переменную в этом блоке. То есть код static < int i = 10 ;>не равнозначен коду static int i = 10 ; .

Читайте также:  Адаптер sony la ea2
категория
Java
дата 17.06.2009
автор yohan
голосов 84

Введение

Как известно, в Java поля (fields) могут принадлежать классу или объекту. Поля, принадлежащие классу, являются статическими, а поля, принадлежащие объекту, – нестатическими. Статические поля доступны без создания объекта класса. Соответственно инициализироваться статические и нестатические поля должны в разное время: одни до создания объекта класса, а другие после.

Типы инициализации полей объектов и классов

Существуют следующие методы инициализации полей:

Название Применимость Описание
Инициализация в месте объявления поля Поля класса, поля объекта Применяется, если инициализация может быть произведена коротким выражением и доступен контекст, необходимый для ее проведения
Инициализационный блок Поля класса, поля объекта Применяется, если инициализационный код неудобно записывать одним выражением или же, например, нужна обработка проверяемых исключений. В случае объектов может применяться для инициализации полей объектов анонимных классов.
Конструктор класса Поля объекта Применяется, если для инициализации нужны параметры конструктора

Далее мы рассмотрим каждый тип инициализации подробнее.

Инициализация статических полей в месте объявления

Начнем с примера:

Здесь инициализируется статическое поле SIZE класса Integer. Сама инициализация произойдет во время загрузки класса. В этом легко убедиться выполнив следующий код:

В результате будет выведено:

Как видно из вывода переменная i инициализируется в результате загрузки класса. Попробуйте выполнить код, закомментировав строку, содержащую Class.forName(. ).

Инициализация в статическом блоке

В некоторых случаях инициализацию неудобно проводить в месте объявления переменной. Например, если в результате выполнения инициализирующего выражения происходит проверяемое исключение. Или же, если инициализация производится путем выполнения кода, который не может быть представлен в виде выражения. Для таких случаев в Java предусмотрен специальный языковой элемент – инициализационный статический блок. Покажем на примере:

Переменная alphabet инициализируется в статическом блоке. Инициализация происходит во время загрузки класса аналогично как и в предыдущем примере.

Инициализация статических полей в месте объявления и статические блоки выполняются в порядке их объявления в классе. Давайте выполним следующий код:

На консоль будет выведено:

Инициализация полей объекта

В отличии от полей класса, поля объекта инициализируются во время конструирования экземпляра класса. В Java существует 3 типа такой инициализации:

  • инициализация в месте объявления
  • инициализация в нестатическом блоке
  • инициализация в конструкторе

Инициализация полей объекта в месте объявления

Покажем на примере:

Инициализация поля posts будет произведена во время конструирования объекта Blog.

Инициализация полей объекта в нестатическом блоке

Использование инициализационных блоков является альтернативой предыдущему способу инициализации. Данный тип инициализации может использоваться, если:

  • во время инициализации необходимо обработать проверяемое исключение
  • значение поля не удобно вычислять с помощью выражения (например, для этого нужен специально созданный класс или метод, который не хочется создавать только для этих целей)
  • необходимо инициализировать поле анонимного класса (в анонимном классе невозможно объявить конструктор)
Читайте также:  Как извлечь фото из icloud на айфон

Пример обработки проверяемого исключения:

Инициализация полей объекта в конструкторе

Часто инициализацию полей объекта имеет смысл проводить только с учетом значений параметров конструктора. В таких случаях ее производят в самом конструкторе. Пример:

Инициализация в конструкторе и наследование

Выполним следующий код:

В out будет выведено:

Вывод свидетельствует о том, что инициализация выполнялась следующим образом:

  • конструктор B первым делом вызвал конструктор предка – класса A
  • конструктор A проинициализировал поле a объекта А
  • при возврате из конструктора A, конструктор B проинициализировал поле b объекта B

Порядок инициализации полей объекта

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

В результате выполнения получим:

Вывод свидельствует о том что:

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

Результат декомипляции предыдущего примера

Ну и напоследок давайте декомпилируем следующий код с помощью Jad:

Получился следующий листинг:

Интересно, что компилятор перенес всю нестатическую инициализацию объекта в конструктор класса. При этом статический инициализационный блок остался без изменений.

Выводы

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


Желаю удачи!
Дмитрий Пекар, июнь 2009

Если Вам понравилась статья, проголосуйте за нее

Голосов: 84 Голосовать

Статические блоки и статическая инициализация используются для инициализации статических полей в Java. Мы объявляем статический блок в тот момент, когда хотим проинициализировать статические поля в классе.

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

Статический блок выполняется до вызова конструктора.

Также можно сказать что статические поля и методы принадлежат классу, нестатические — объекту.

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

Ваш адрес email не будет опубликован. Обязательные поля помечены *