by lazy: szczegółowe omówienie odroczonej inicjalizacji
Poznaj tryby leniwej inicjalizacji: SYNCHRONIZED, PUBLICATION i NONE.
by lazy: szczegółowe omówienie odroczonej inicjalizacji to bezpłatna lekcja Kotlin Academy na CoddyKit. To lekcja 1 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Kotlin Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Kotlin Academy zawiera 4 lekcji w sumie.
Czym jest by lazy?
by lazy odracza inicjalizację elementu val do chwili pierwszego dostępu. Lambda jest uruchamiana raz, a jej wynik jest buforowany.
val greeting: String by lazy {
println("Computing...")
"Hello, Kotlin!"
}
fun main() {
println(greeting) // prints Computing... then Hello, Kotlin!
println(greeting) // prints Hello, Kotlin! (cached)
}Składnia lazy
Delegat by lazy przyjmuje lambdę zwracającą typ wartości wywnioskowany z deklaracji właściwości.
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
}Tryb SYNCHRONIZED (domyślny)
Domyślnie lazy używa LazyThreadSafetyMode.SYNCHRONIZED: tylko jeden wątek inicjalizuje wartość.
val heavyResource: String by lazy(LazyThreadSafetyMode.SYNCHRONIZED) {
Thread.sleep(100) // simulate work
"Resource ready"
}
fun main() { println(heavyResource) }Tryb PUBLICATION
PUBLICATION pozwala wielu wątkom na równoczesną inicjalizację; wygrywa pierwszy wynik. Należy go używać, gdy inicjalizacja jest tania i nie powoduje efektów ubocznych.
val config: Map<String, String> by lazy(LazyThreadSafetyMode.PUBLICATION) {
mapOf("host" to "localhost", "port" to "8080")
}
fun main() { println(config["host"]) }Tryb NONE
NONE nie wiąże się z narzutem synchronizacji. Należy go używać wyłącznie w kontekstach jednowątkowych, gdy wydajność ma znaczenie.
val singleThreadValue: Int by lazy(LazyThreadSafetyMode.NONE) {
42
}
fun main() { println(singleThreadValue) }Lazy w klasie
by lazy wewnątrz klasy inicjalizuje wartość przy pierwszym dostępie do właściwości, co przydaje się przy kosztownych obliczeniach zależnych od stanu instancji.
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 a lateinit
Należy użyć by lazy dla elementu val ze złożoną inicjalizacją. lateinit należy użyć dla elementu var przypisywanego z zewnątrz (np. w testach lub podczas wstrzykiwania zależności).
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)
}Sprawdzanie isInitialized
Można sprawdzić, czy właściwość lazy została zainicjalizowana, za pomocą .isInitialized() — ale wyłącznie przez odwołanie do delegata.
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 z zależnością
Właściwości lazy mogą odwoływać się do innych właściwości lazy, tworząc łańcuch leniwej inicjalizacji.
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)
}Praktyka: usługa Singleton
Należy używać by lazy w deklaracjach object, aby inicjalizować ciężkie singletony dopiero na żądanie.
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
}Leniwa kompilacja wyrażeń regularnych
Kompilowanie wyrażeń regularnych jest kosztowne. Należy użyć by lazy, aby skompilować je raz i wielokrotnie używać, unikając powtarzalnego narzutu.
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
}Szybkie sprawdzenie
Którego trybu lazy należy użyć w środowisku jednowątkowym, aby uzyskać maksymalną wydajność?
Podsumowanie
by lazy uruchamia swoją lambdę raz przy pierwszym dostępie i buforuje wynik. Należy wybrać SYNCHRONIZED (domyślnie) dla bezpieczeństwa wątkowego, PUBLICATION dla współbieżnej, idempotentnej inicjalizacji oraz NONE dla wydajności w środowisku jednowątkowym.
Często zadawane pytania
Czy lekcja „by lazy: szczegółowe omówienie odroczonej inicjalizacji” jest bezpłatna?
Tak — pełny tekst „by lazy: szczegółowe omówienie odroczonej inicjalizacji” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Kotlin Academy, przejdź na CoddyKit PRO. Kurs Kotlin Academy zawiera 4 lekcji w sumie.
Co nauczysz się w „by lazy: szczegółowe omówienie odroczonej inicjalizacji”?
Poznaj tryby leniwej inicjalizacji: SYNCHRONIZED, PUBLICATION i NONE. Ćwiczysz Kotlin Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć Kotlin Academy?
Nie wymagamy żadnego doświadczenia. Kotlin Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 1 z 4.
Ile czasu zajmuje lekcja „by lazy: szczegółowe omówienie odroczonej inicjalizacji”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji Kotlin Academy?
Tak. Każda lekcja Kotlin Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.
Wszystkie lekcje w tym kursie
- by lazy: szczegółowe omówienie odroczonej inicjalizacji
- Delegaty observable i vetoable
- Pisanie własnego delegata ReadWriteProperty
- Delegaty dla Preferences, właściwości opartych na Map i logowania