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 — локальная установка не требуется.
Все уроки этого курса
- by lazy: подробный разбор отложенной инициализации
- Делегаты observable и vetoable
- Написание пользовательского делегата ReadWriteProperty
- Делегаты для настроек, свойств на основе карт и ведения журнала