lateinit i leniwa inicjalizacja
Używaj lateinit dla właściwości przypisywanych z opóźnieniem oraz by lazy do odroczonych obliczeń.
lateinit i leniwa inicjalizacja to bezpłatna lekcja Kotlin Academy na CoddyKit. To lekcja 4 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.
Dwa narzędzia do późnej inicjalizacji
Czasami nie można zainicjalizować właściwości podczas tworzenia obiektu. Kotlin udostępnia lateinit (dla var, przypisywanego później) oraz by lazy (dla val, obliczanego przy pierwszym dostępie).
Podstawy lateinit
lateinit var odracza inicjalizację. Zmienna musi być niepustą, nieprymitywną właściwością var. Dostęp przed przypisaniem wartości powoduje wyjątek UninitializedPropertyAccessException.
class Service {
lateinit var name: String
fun init(value: String) { name = value }
}
fun main() {
val s = Service()
s.init("MyService")
println(s.name)
}Dlaczego używać lateinit?
lateinit należy stosować w przypadku wstrzykiwania zależności, obiektów testowych lub cykli życia zarządzanych przez frameworki (widoki Android, beany Spring), gdy inicjalizacja odbywa się poza konstruktorem.
class Repository {
lateinit var db: String // assigned later by DI framework
fun query() = "querying $db"
}
fun main() {
val r = Repository()
r.db = "postgres://localhost"
println(r.query())
}Sprawdzanie isInitialized
Można sprawdzić, czy właściwości lateinit przypisano wartość, używając ::propName.isInitialized.
class Foo {
lateinit var bar: String
fun status() = if (::bar.isInitialized) "set to $bar" else "unset"
}
fun main() {
val f = Foo()
println(f.status()) // unset
f.bar = "hi"
println(f.status())
}Ograniczenia lateinit
Nie można używać lateinit dla typów prymitywnych (Int, Boolean itd.), typów nullable ani val. Kompilator wymusza przestrzeganie tych zasad.
// VALID:
lateinit var name: String
// INVALID:
// lateinit var count: Int // primitives not allowed
// lateinit val constant: String // val not allowed
// lateinit var maybe: String? // nullable not allowed
fun main() { name = "ok"; println(name) }Podstawy by lazy
by lazy odracza inicjalizację właściwości val do pierwszego dostępu. Lambda jest wykonywana raz, a jej wynik jest buforowany.
val expensive: String by lazy {
println("Computing...")
"result"
}
fun main() {
println(expensive) // Computing... then result
println(expensive) // result (cached)
}Dlaczego używać by lazy?
by lazy należy stosować, gdy inicjalizacja jest kosztowna i może nie być potrzebna (wynik można zachować do późniejszego użycia) albo gdy inicjalizacja zależy od innych, już utworzonych właściwości.
class Config {
val parsed: Map<String, String> by lazy {
println("parsing config...")
mapOf("host" to "localhost", "port" to "8080")
}
}
fun main() {
val c = Config()
println("config object created — not parsed yet")
println(c.parsed["host"]) // now parses
println(c.parsed["port"]) // cached
}Tryby bezpieczeństwa wątkowego lazy
Domyślnie by lazy używa LazyThreadSafetyMode.SYNCHRONIZED. Należy użyć PUBLICATION w przypadku inicjalizacji, która może być wykonywana współbieżnie, oraz NONE dla wydajności w aplikacji jednowątkowej.
val safe: String by lazy { "thread-safe" }
val fast: String by lazy(LazyThreadSafetyMode.NONE) { "fast, single-thread" }
fun main() {
println(safe)
println(fast)
}lateinit a lazy
lateinit: var, któremu wartość jest przypisywana z zewnątrz. by lazy: val, obliczany przez samą właściwość przy pierwszym dostępie.
class Demo {
lateinit var injected: String // assigned by caller
val computed: String by lazy { "computed once" }
}
fun main() {
val d = Demo()
d.injected = "from outside"
println(d.injected)
println(d.computed)
}Odczytywanie innych właściwości przez lazy
Właściwość lazy może odczytywać inne, wcześniej zainicjalizowane właściwości i łączyć ich wartości.
class User(val first: String, val last: String) {
val fullName: String by lazy { "$first $last" }
}
fun main() {
val u = User("Ada", "Lovelace")
println(u.fullName)
}Wzorzec praktyczny
W tej samej klasie można połączyć lateinit do wstrzykiwania zależności z by lazy do przechowywania stanu pochodnego.
class App {
lateinit var config: Map<String, String>
val host: String by lazy { config["host"] ?: "localhost" }
}
fun main() {
val app = App()
app.config = mapOf("host" to "api.example.com")
println(app.host) // api.example.com
}Szybkie sprawdzenie
Które słowo kluczowe odracza inicjalizację właściwości val do pierwszego dostępu?
Podsumowanie
lateinit var służy do niepustych, mutowalnych właściwości, którym frameworki lub mechanizmy DI przypisują wartość później. val by lazy służy do wartości tylko do odczytu, które powinny zostać obliczone raz przy pierwszym dostępie. Stan można sprawdzić za pomocą ::prop.isInitialized.
Ucz się Kotlin dzięki korepetycjom AI — za darmo
Pisz i uruchamiaj kod w przeglądarce, otrzymuj natychmiastową pomoc od korepetytora AI dostępnego 24/7 i kontynuuj naukę w sieci lub w aplikacji.
- Kursy
- 51
- Lekcje
- 203
Często zadawane pytania
Czy lekcja „lateinit i leniwa inicjalizacja” jest bezpłatna?
Tak — pełny tekst „lateinit i leniwa inicjalizacja” 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 „lateinit i leniwa inicjalizacja”?
Używaj lateinit dla właściwości przypisywanych z opóźnieniem oraz by lazy do odroczonych obliczeń. Ć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 4 z 4.
Ile czasu zajmuje lekcja „lateinit i leniwa inicjalizacja”?
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
- Konstruktor główny i parametry właściwości
- Bloki init i kolejność inicjalizacji
- Własne gettery i settery z field
- lateinit i leniwa inicjalizacja