04.05.2022

Блок инициализации


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

Мотивация

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

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

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

... static { // Static block code } ...

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

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

    public class Car { static Map<String, Set<Car>> catalog; static { catalog = new HashMap<String, Set<Car>>(); catalog.put("model105", new HashSet<Car>()); catalog.put("model125", new HashSet<Car>()); catalog.put("model140", new HashSet<Car>()); catalog.put("model201", new HashSet<Car>()); } public Car (String model) { catalog.get(model).add(this); // ... } // ... }

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

    Динамический блок инициализации

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

    ... { // Instance block code } ...

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

    public class Car { static int count = 0; public Car (String model) { init(); // ... } public Car (String model, Double price) { init(); // ... } private void init() { count++; System.out.println("Hello everyone, we have " + count + " cars now!"); } // ... }

    равнозначен коду:

    public class Car { static int count = 0; public Car (String model) { // ... } public Car (String model, Double price) { // ... } { count++; System.out.println("Hello everyone, we have " + count + " cars now!"); } // ... }

    Порядок выполнения загрузки

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

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

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

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

    public class T { static int i = 5; static { i = 10; } static { i = i * 3; } }

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

    public class T { static { i = 10; } static int i = 5; static { i = i * 3; } }

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

    Возможные проблемы

    Использование переменной до её определения

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

    public class T { static { i = 5; i = i + 1; } static int i = 5; }

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

    Локальная статическая переменная

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

    public class T { static { int i = 10; } public static void main(String[] args) { System.out.println(i); } }

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


    Похожие новости:

    Зачем нужны модульные блок-контейнеры?

    Зачем нужны модульные блок-контейнеры?
    Блок-контейнеры и блок-модули – виды сооружений полной заводской готовности. В их состав входят жесткая рама, высокопрочный каркас из стали с антикоррозионной обработкой, кровля, настил пола,

    Блок, Давид Семёнович

    Блок, Давид Семёнович
    Давид Семёнович Блок (1888—1948) — советский композитор, звукорежиссёр и дирижёр. Организатор (1941) и первый руководитель Государственного оркестра Министерства кинематографии СССР. Заслуженный

    Л1839ВМ1

    Л1839ВМ1
    Микросхема Л1839ВМ1 — однокристальный 32-разрядный микропроцессор, изготовленный по КМОП-технологии с проектными нормами 3 мкм, с двойной металлизацией. Микросхема Л1839ВМ1 предназначена для

    Особенности строения проксимального ряда заплюсны у животных

    Особенности строения проксимального ряда заплюсны у животных
    У жвачных суставной блок таранной кости лежит в сагиттальной плоскости. Дистальная суставная поверхность тоже имеет блок для соединения с центральной костью, которая срастается у жвачных с 4+5
    Комментариев пока еще нет. Вы можете стать первым!

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

    Ваше Имя:
    Ваш E-Mail:
    Введите два слова, показанных на изображении: *
    Популярные новости
    Жилой квартал Лесопарковый в Челябинске: отличительные особенности
    Жилой квартал Лесопарковый в Челябинске: отличительные особенности
    Подобрать квартиру в Челябинске с первого раза могут только люди, не предъявляющие особых...
    Стоимость дизайн-проекта интерьера в Краснодарской студии
    Стоимость дизайн-проекта интерьера в Краснодарской студии
    Дизайн-проект реализует определенные задачи. Он формирует комфортное помещение для жизни,...
    Тепловые пункты: преимущества установок и где заказать их изготовление
    Тепловые пункты: преимущества установок и где заказать их изготовление
    Тепловой пункт представляет собой комплекс устройств, предназначенных для поставки тепловой энергии...
    Все новости