Шаг 157.
Основы Kotlin.
Инициализация. Порядок инициализации

    На этом шаге мы рассмотрим порядок инициализации свойств.

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

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

class Player(_name: String, val health: Int) {
    val race = "DWARF"
    var town = "Bavaria"
    val name = _name
    val alignment: String
    private var age = 0
    init {
        println("initializing player")
        alignment = "GOOD"
    }
    constructor(_name: String) : this(_name, 100) {
        town = "The Shire"
    }
}
fun main(args: Array<String>) {
    Player("Madrigal")
}

    Обратите внимание, что экземпляр класса Player создается вызовом вспомогательного конструктора Player("Madrigal").

    На рисунке 1 вверху показан класс Player, а внизу - декомпилированный байткод Java, отражающий итоговый порядок инициализации.


Рис.1. Порядок инициализации класса Player (скомпилированный байт-код)

    Итак, инициализация выполняется в следующем порядке:

  1. Создаются и инициализируются свойства, встроенные в объявление главного конструктора (val health: Int).
  2. Выполняются операции присваивания на уровне класса (val race = "DWARF", val town = "Bavaria", val name = _name).
  3. Выполняется блок init, присваивающий значения свойствам и вызывающий функции (alignment = "GOOD", вызов println).
  4. Выполняется тело вспомогательного конструктора, в котором присваиваются значения свойствам и вызываются функции (town = "The Shire").

    Порядок выполнения блока init (пункт 3) и операций присваивания на уровне класса (пункт 2) зависит от порядка, в котором они указаны. Если блок init поместить после операций присваивания значений свойствам на уровне класса, он выполнится после них.

    Обратите внимание на отсутствие кода инициализации одного из свойств - age: хотя оно объявляется и инициализируется, оно находится на уровне свойств класса. Это связано с тем, что ему присваивается значение 0 (значение по умолчанию для простого типа int в Java), поэтому его можно не инициализировать явно, и компилятор просто оптимизировал код, опустив ненужные инструкции.

    На следующем шаге мы рассмотрим задержку инициализации.




Предыдущий шаг Содержание Следующий шаг