Kotlin之 lateinit 和 by lazy(延遲初始化)
一,lateinit(延遲初始化屬性)(只能用在var變量上)
一般地,屬性聲明爲非空類型必須在構造函數中初始化(我們知道,kotlin中默認是空安全的,任何屬性的聲明都必須有初始化值,如果支持可空”?”,才能把屬性聲明爲null)。然而這樣經常不方便,例如:屬性可以通過依賴注入來初始化,或者單元測試的setup方法中初始化,這種情況下,你不能在構造函數內提供一個非空初始器,但你仍然想在類體中引用該屬性時避免空檢查。爲處理這種情況,我們可以使用lateinit
val nameA:String //報紅線 提示如下
Property must be initialized or be abstract
lateinit var name:String //lateinit可以避免這種情況
該修飾只能用於類體中(不是在主構造函數中)聲明的var屬性,注意是var(可變屬性)並且僅當該屬性沒有自定義getter或setter時,該屬性必須是非空類型,並且不能是原生類型。
在初始化前訪問一個lateinit屬性會拋出一個特定異常,該異常明確標識該屬性被訪問及它沒有初始化的事實。
by lazy(惰性初始化)(只能用在val變量上)
惰性初始化是一種常見的模式,直到第一次訪問該屬性的時候,才根據需要創建對象的一部分,當初始化過程消耗大量資源並且在使用對象時並不總是需要數據時,這個非常有用。
val nameB: String by lazy {
println("getLazy")
"123"
}
println(nameB)
println(nameB)
輸入結果:
getLazy
123
123
首先需要注意的是:
by lazy只能作用於val關鍵字標註的屬性。
當屬性用到的時候纔會初始化”lazy{}”裏面的內容
而且再次調用屬性的時候,只會得到結果,而不會再次執行lazy{}的運行過程
總結:以上可以看出兩個都是用來初始化屬性的,但是有點互補的意思。可以根據不同情況選擇使用。
備註:如果你想要線程安全,使用 blockingLazy(): 它還是按照同樣的方式工作,但保證了它的值只會在一個線程中計算,並且所有的線程都獲取的同一個值。