0Pricing
Kotlin Academy · Урок

by lazy: подробный разбор отложенной инициализации

Изучите режимы ленивой инициализации: SYNCHRONIZED, PUBLICATION и NONE.

«by lazy: подробный разбор отложенной инициализации» — бесплатный урок Kotlin Academy на CoddyKit. Это урок 1 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Kotlin Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Kotlin Academy содержит 4 уроков всего.

Что такое by lazy

by lazy откладывает инициализацию val до первого обращения. Лямбда выполняется один раз, а результат кэшируется.

val greeting: String by lazy {
    println("Computing...")
    "Hello, Kotlin!"
}
fun main() {
    println(greeting) // prints Computing... then Hello, Kotlin!
    println(greeting) // prints Hello, Kotlin! (cached)
}

Синтаксис lazy

Делегат by lazy принимает лямбду, возвращающую тип значения, выведенный из объявления свойства.

val pi: Double by lazy { Math.PI }
val appName: String by lazy { "MyApp v1.0" }
fun main() {
    println(pi)      // 3.141592653589793
    println(appName) // MyApp v1.0
}

Режим SYNCHRONIZED (по умолчанию)

По умолчанию lazy использует LazyThreadSafetyMode.SYNCHRONIZED: значение инициализируется только одним потоком.

val heavyResource: String by lazy(LazyThreadSafetyMode.SYNCHRONIZED) {
    Thread.sleep(100) // simulate work
    "Resource ready"
}
fun main() { println(heavyResource) }

Режим PUBLICATION

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

val config: Map<String, String> by lazy(LazyThreadSafetyMode.PUBLICATION) {
    mapOf("host" to "localhost", "port" to "8080")
}
fun main() { println(config["host"]) }

Режим NONE

NONE не создаёт затрат на синхронизацию. Используйте его только в однопоточных сценариях, где важна производительность.

val singleThreadValue: Int by lazy(LazyThreadSafetyMode.NONE) {
    42
}
fun main() { println(singleThreadValue) }

Lazy в классе

by lazy внутри класса инициализирует свойство при первом обращении к нему, что удобно для ресурсоёмких вычислений, зависящих от состояния экземпляра.

class DatabaseConnection(val url: String) {
    val pool: String by lazy {
        println("Connecting to $url")
        "Pool@$url"
    }
}
fun main() {
    val db = DatabaseConnection("localhost:5432")
    println(db.pool)
}

Lazy и lateinit

Используйте by lazy для val со сложной инициализацией. Используйте lateinit для var, которому значение присваивается извне (например, в тестах или при внедрении зависимостей).

class MyService {
    val computed: List<Int> by lazy { (1..100).toList() }
    lateinit var injected: String
}
fun main() {
    val s = MyService()
    s.injected = "injected value"
    println(s.computed.size)
    println(s.injected)
}

Проверка isInitialized

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

val myLazy: String by lazy { "initialized" }
fun main() {
    val ref = ::myLazy
    // No direct isInitialized on val lazy, but we can check via delegate
    println(myLazy)
}

Lazy с зависимостью

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

val baseUrl: String by lazy { "https://api.example.com" }
val usersUrl: String by lazy { "$baseUrl/users" }
val postsUrl: String by lazy { "$baseUrl/posts" }
fun main() {
    println(usersUrl)
    println(postsUrl)
}

Практика: одиночный сервис

Используйте by lazy в объявлениях object, чтобы инициализировать ресурсоёмкие одиночные экземпляры по требованию.

object Analytics {
    val client: String by lazy {
        println("Initializing analytics client")
        "AnalyticsClient@ready"
    }
}
fun main() {
    println("App started")
    println(Analytics.client) // initialized on first use
    println(Analytics.client) // cached
}

Ленивая компиляция регулярных выражений

Компиляция регулярного выражения требует ресурсов. Используйте by lazy, чтобы выполнить компиляцию один раз и повторно использовать результат, избегая лишних затрат.

val emailRegex: Regex by lazy {
    Regex("^[A-Za-z0-9+_.-]+@(.+)$")
}
fun isValidEmail(email: String) = emailRegex.matches(email)
fun main() {
    println(isValidEmail("user@example.com")) // true
    println(isValidEmail("bad-email"))         // false
}

Быстрая проверка

Какой режим lazy следует использовать в однопоточной среде для максимальной производительности?

Итоги

by lazy выполняет лямбду один раз при первом обращении и кэширует результат. Выбирайте SYNCHRONIZED (по умолчанию) для безопасности в многопоточной среде, PUBLICATION для параллельной идемпотентной инициализации, а NONE — для производительности в однопоточной среде.

Часто задаваемые вопросы

Урок «by lazy: подробный разбор отложенной инициализации» бесплатный?

Да — полный текст урока «by lazy: подробный разбор отложенной инициализации» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Kotlin Academy, подпишись на CoddyKit PRO. Курс Kotlin Academy содержит 4 уроков всего.

Чему я научусь в уроке «by lazy: подробный разбор отложенной инициализации»?

Изучите режимы ленивой инициализации: SYNCHRONIZED, PUBLICATION и NONE. Ты практикуешь Kotlin Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать Kotlin Academy?

Предыдущий опыт не требуется. Kotlin Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 1 из 4.

Сколько времени занимает урок «by lazy: подробный разбор отложенной инициализации»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке Kotlin Academy?

Да. Каждый урок Kotlin Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. by lazy: подробный разбор отложенной инициализации
  2. Делегаты observable и vetoable
  3. Написание пользовательского делегата ReadWriteProperty
  4. Делегаты для настроек, свойств на основе карт и ведения журнала
← Назад к Kotlin Academy