Порядок инициализации статических блоков java

Порядок загрузки классов, статические данные…

— Привет, Амиго! Слышала, Риша рассказал тебе новую и очень интересную тему?!

— Моя тема будет не менее интересной. Я хочу рассказать тебе о загрузке в память классов.

Классы в Java – это файлы на диске, содержащие байт-код – скомпилированный Java-код.

— Java-машина не загружает их без необходимости. Как только где-то в коде происходит обращение к классу, Java-машина проверяет – загружен ли он. И если нет, то загружает и инициализирует его.

Инициализация класса – это присваивание значений всех его статических переменных и вызов всех статических блоков.

— Похоже на вызов конструктора у объекта. А что такое статический блок?

— Если для инициализации переменных объекта нужно выполнить сложный код (например, что-то загрузить из файла), мы можем сделать это в конструкторе. Статические переменные такой возможности лишены. Но т.к. потребность в этом осталась, в классы можно добавить статический блок или блоки, которые по сути своей эквивалентны вызову статических конструкторов.

class Cat < public static int catCount = 0 ; public static String namePrefix; static < Properties p = new Properties(); p.loadFromFile("cat.properties"); namePrefix = p.get("name-prefix"); >public static int maxCatCount = 50; static < Properties p = new Properties(); p.loadFromFile("max.properties"); if (p.get("cat-max") != null) maxCatCount = p.getInt("cat-max"); >> 

Внимание! Объявляется набор кода на JavaRush. Включите режим повышенной внимательности, расслабьте пальцы, читайте код и… набирайте его в соответствующем окошке. Набор кода — не бесполезное занятие, как может показаться на первый взгляд: вы привыкаете к синтаксису и запоминаете его (современные IDE редко дают вам это сделать).

Читайте также:  Who have php id

Это очень похоже на то, что происходит при вызове конструктора. Я даже записала это в виде несуществующего статического конструктора.

Java-университет

Самый популярный комментарий рекомендует эту ссылку http://vscode.ru/prog-lessons/staticheskiy-blok-v-java.html НО тем кто не понял советую блок статик из примера в статье поставить в конец и вы увидите что sout вывел его раньше именно за счет того что кусок кода в блоке статик JVM прочитает раньше остального класса.

Несколько слов о порядке инициалиазации. Может быть полезным для тех, кто пытается собрать всю информацию воедино. При первом обращении к классу выполняются все статические инициализаторы и блоки инициализации в порядке их появления в коде. Причём изначально выполняются статические блоки инициализации и инициализаторы всех предков, начиная с базового класса, если целевой класс принимает участи в иерарахии наследования. P.S. Под первым обращением к классу подразумевается любое взаимодействие с классом. Таковым может быть прямое обращение к полям или методам класса, а может быть и использование ссылочной переменной соответствующего типа (в нашем случае идёт речь о переменной рассматриваемого с контексте инициализации типа). Как уже написал, порядок имеет имеет значение. Если в коде идёт поле, за которым следует блок, а потом снова поле, то инициализация будет выполняться именно в таком порядке. Полям в любом случае изначально присваиваются значения по умолчанию, а потом уже те значения, которые были указаны непосредственно в коде. Когда мы вызываем конструктор класса (при создании нового экземпляра класса), то изначально выделяется память под новый объект. Это означает, что мы выделяем место под хранение всех полей объекта, которым на начальном этапе будут присвоены значения по умолчанию. После этого срабатывают инициализаторы полей и блоки иницилазиации экземпляра (это такие же блоки, только без ключевого слова static), после чего отрабатывает код из конструктора. Двигаемся мы как бы слоями, начиная с самого базового класса и спускаясь вниз к целевому классу.

Источник

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

Java-университет

Привет! Сегодняшняя лекция будет довольно. э-э-э. разносторонней 🙂 В том смысле, что мы рассмотрим широкий круг тем, но все они будут касаться процесса создания объекта . Мы разберем его от начала до конца: как вызываются конструкторы, как и в каком порядке инициализируются поля (в том числе статические) и т.д. Некоторые моменты, рассматриваемые в статье, мы затрагивали ранее, поэтому можешь пробежать глазами материал о конструкторе базовых классов. Для начала давай вспомним как происходит создание объекта. Ну, как этот процесс выглядит с точки зрения разработчика, ты хорошо помнишь: создал класс, написал new — и все готово 🙂 Здесь поговорим о том, что происходит внутри компьютера и Java-машины, когда мы пишем, например:

Порядок действий при создании объекта - 2

Мы ранее уже говорили об этом, но на всякий случай вспомним:

  1. Сначала для хранения объекта выделяется память.
  2. Далее Java-машина создает ссылку на этот объект (в нашем случае ссылка — это Cat cat ).
  3. В завершение происходит инициализация переменных и вызов конструктора (этот процесс мы рассмотрим подробнее).

Кроме того, из лекции о жизненном цикле объекта ты наверняка помнишь, что он длится до тех пор, пока на него существует хоть одна ссылка. Если же их не осталось, объект станет добычей для сборщика мусора. Первые два пункта особых вопросов вызывать не должны. Выделение памяти — процесс несложный, да и результат может быть только один из двух: либо память есть, либо ее нет 🙂 Создание ссылки — тоже ничего необычного. А вот пункт номер три представляет из себя целый набор операций, идущих в строго определенном порядке. Я не фанат зубрежки как средства что-то выучить, но вот в этом процессе тебе стоит хорошо разобраться, и знать этот порядок нужно наизусть . Когда мы говорили о процессе создания объектов на прошлых лекциях, ты еще ничего толком не знал о наследовании, поэтому объяснить некоторые моменты было проблематично. Сейчас же объем твоих знаний достаточно велик, и мы, наконец, можем рассмотреть этот вопрос полноценно 🙂 Итак, третий пункт гласит что “в завершение происходит инициализация переменных и вызов конструктора.” Но в каком порядке все это совершается? Для лучшего понимания давай создадим два простейших класса — родителя и наследника:

 public class Car < public static int carCounter = 0; private String description = "Абстрактная машина"; public Car() < >public String getDescription() < return description; >> public class Truck extends Car < private static int truckCounter = 0; private int yearOfManufacture; private String model; private int maxSpeed; public Truck(int yearOfManufacture, String model, int maxSpeed) < this.yearOfManufacture = yearOfManufacture; this.model = model; this.maxSpeed = maxSpeed; Car.carCounter++; truckCounter++; >> 

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

  1. Первое что произойдет — проинициализируются статические переменные класса Car . Да-да, именно класса Car , а не Truck . Статические переменные инициализируются еще до вызова конструкторов, и начинается это в классе-родителе. Давай попробуем проверить. Выставим счетчик carCounter в классе Car на 10 и попробуем вывести его в консоль в обоих конструкторах — Car и Truck .
 public class Car < public static int carCounter = 10; private String description = "Абстрактная машина"; public Car() < System.out.println(carCounter); >public String getDescription() < return description; >> public class Truck extends Car < private static int truckCount = 0; private int yearOfManufacture; private String model; private int maxSpeed; public Truck(int yearOfManufacture, String model, int maxSpeed) < System.out.println(carCounter); this.yearOfManufacture = yearOfManufacture; this.model = model; this.maxSpeed = maxSpeed; Car.carCounter++; truckCount++; >> 

Мы специально поставили вывод в консоль в самом начале конструктора Truck , чтобы точно знать: поля грузовика на момент вывода carCounter ’a в консоль еще не были инициализированы. А вот и результат:

 public class Truck extends Car < private static int truckCounter = 10; private int yearOfManufacture; private String model; private int maxSpeed; public Truck(int yearOfManufacture, String model, int maxSpeed) < System.out.println(truckCounter); this.yearOfManufacture = yearOfManufacture; this.model = model; this.maxSpeed = maxSpeed; Car.carCounter++; truckCounter++; >> 
 public class Car < public static int carCounter = 10; private String description = "Начальное значение поля description"; public Car() < System.out.println(description); description = "Абстрактная машина"; System.out.println(description); >public String getDescription() < return description; >> 
 Начальное значение поля description Абстрактная машина 
 public Car() < System.out.println("Привет из конструктора Car!"); >public Truck(int yearOfManufacture, String model, int maxSpeed)
 Привет из конструктора Car! Привет из конструктора Truck! 
public class Truck extends Car < private static int truckCounter = 10; private int yearOfManufacture; private String model; private int maxSpeed = 150; public Truck(int yearOfManufacture, String model, int maxSpeed) < System.out.println("Изначальное значение maxSpeed text-bold">на момент старта конструктора Truck значение maxSpeed уже было равно 150!

  • Вызывается конструктор дочернего класса Truck.

    И только сейчас, в последнюю очередь, будет вызван конструктор того класса, объект которого мы создаем!

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

    Как видишь, «конструирование» грузовика, т.е. процесс создания объекта — штука непростая. Но мы, кажется, разобрали его до самых мелочей :)

  • Порядок действий при создании объекта - 3Почему так важно хорошо разбираться в этом процессе? Представь, насколько неожиданными могут оказаться результаты создания обычного объекта, если не знать точно, что происходит «под капотом» :) Самое время вернуться к курсу и решить несколько задач! Удачи, и до новых встреч :)
    Pavlo Plynko
    Java-разработчик в CodeGym
    До того, как стать разработчиком, Павел 15 лет посвятил системному администрированию, но понимал, что не хочет заниматься этим всю . [Читать полную биографию]
    Комментарии (147)
    ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
    ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
    МаксимУровень 15
    6 июля 2023
    Спасибо автору статьи за материал и разъяснение. У меня вопрос к JAVARASH: почему не позаботились о том, что бы рассказать зачем нужен статический блок инициализации и когда он инициализируется в предке и потомке? Вот отличный шортс на эту тему https://www.youtube.com/shorts/gBG8McovcDw
    ИсламУровень 32
    20 июня 2023
    Nice
    NikitaУровень 28
    8 июня 2023
    Напишу и сохраню, простите если в 100-ый раз тут пишут :) _____________________________________________________________________________________ 1. Статические переменные класса родителя (по умолчанию или с заданными значениями, если в коде выше статических блоков) 2. Статические блоки класса родителя 3. Статические переменные базового класса (по умолчанию или с заданными значениями, если в коде выше статических блоков) 4. Статические блоки базового класса 5. Не статические (у экземпляра) переменные класса родителя (по умолчанию или с заданными значениями, если в коде выше статических блоков) 6. Не статические (у экземпляра) блоки класса родителя 7. Конструктор класса родителя 8. Не статические (у экземпляра) переменные базового класса (по умолчанию или с заданными значениями, если в коде выше статических блоков) 9. Не статические (у экземпляра) блоки базового класса 10. Конструктор базового класса _____________________________________________________________________________________ Обращение только к статической переменной/функции (класс не был в памяти): а) Есть наследование: 1-4; б) Нет наследования: 3-4; Создание экзмепляра (класс не был в памяти): а) Есть наследование: 1-10; б) Нет наследования: 3,4,8,9,10; Создание экзмепляра (уже ранее был использован класс или ранее был создан аналогичный экзмепляр класса - класс был в памяти): а) Есть наследование: 5-10; б) Нет наследования: 8-10; P.S. чуть дальше будет отличная задача на эту тему: task1524
    SplitCoreУровень 41
    22 мая 2023
    Статические переменные родителя-> статические переменные потомка-> нестатические переменные родителя-> конструктор родителя-> нестатические переменные потомка-> конструктор потомка
    LeonidMessin22Уровень 24
    29 марта 2023
    Еще можно поставить точку останова, запустить отладку и пройтись по шагам с помощью клавиши F7. Будет наглядно.
    MuratУровень 30
    26 марта 2023
    Прекрасная статья! Спасибо! Отлично закрепил данную тему) думаю теперь в голове надолго останется порядок: Статические поля базового класса -> Статические поля классов наследников -> Нестатические поля базового класса -> Конструктор базового класса -> Нестатические поля классов наследников -> Конструктор классов наследников
    Anonymous #3265332Уровень 30
    19 марта 2023
    Из комментариев к лекциям я получаю более внятное объяснение происходящего.
    Anonymous #3116449Уровень 18
    26 февраля 2023
    переписаться бы код примеров на более демонстративные как оказалось, не я такой один и ниже комментарий описывает все подробнее. код стать - вывод статической переменной в конструкторе класса Car
    public Car()
     public class Car < public static int carCounter = 0; static < System.out.println("Static section of Car() class before constructor()"); System.out.println("carCounter = " + carCounter); >private String description = "Абстрактная машина"; public Car()

    Источник

    Собеседование по Java — ООП (вопросы и ответы). Часть 2

    Вторая часть ответов и вопросов для собеседования по ООП в Java.

    Вопросы. Часть 2

    21. Зачем нужен оператор instanceof?
    22. Зачем нужны и какие бывают блоки инициализации?
    23. Каков порядок вызова конструкторов и блоков инициализации двух классов: потомка и его предка?
    24. Где и для чего используется модификатор abstract?
    25. Можно ли объявить метод абстрактным и статическим одновременно?
    26. Что означает ключевое слово static?
    27. К каким конструкциям Java применим модификатор static?
    28. Что будет, если в static блоке кода возникнет исключительная ситуация?
    29. Можно ли перегрузить static метод?
    30. Что такое статический класс, какие особенности его использования?
    31. Какие особенности инициализации final static переменных?
    32. Как влияет модификатор static на класс/метод/поле?
    33. О чем говорит ключевое слово final?
    34. Дайте определение понятию “интерфейс”.
    35. Какие модификаторы по умолчанию имеют поля и методы интерфейсов?
    36. Почему нельзя объявить метод интерфейса с модификатором final или static?
    37. Какие типы классов бывают в java (вложенные… и.т.д.)
    38. Какие особенности создания вложенных классов: простых и статических.
    39. Что вы знаете о вложенных классах, зачем они используются? Классификация, варианты использования, о нарушении инкапсуляции.
    40. В чем разница вложенных и внутренних классов?
    41. Какие классы называются анонимными?
    42. Каким образом из вложенного класса получить доступ к полю внешнего класса?

    Ответы. Часть 2

    21. Зачем нужен оператор instanceof?

    Оператор instanceof возвращает true, если объект является экземпляром класса или его потомком.

    Источник

    Оцените статью