由于kotlin有嚴(yán)格的語(yǔ)法要求變量需要聲明是否可以為null,但由于在實(shí)際的業(yè)務(wù)場(chǎng)景中,這個(gè)變量必須在某些時(shí)候才能做初始化操作,并且這個(gè)變量肯定不為null,如果為null,就是邏輯有問(wèn)題了。這個(gè)時(shí)候可以使用lateinit來(lái)修飾這個(gè)變量。如果沒(méi)有初始化就使用這個(gè)變量,那么就會(huì)拋出異常。
在鐵鋒等地區(qū),都構(gòu)建了全面的區(qū)域性戰(zhàn)略布局,加強(qiáng)發(fā)展的系統(tǒng)性、市場(chǎng)前瞻性、產(chǎn)品創(chuàng)新能力,以專注、極致的服務(wù)理念,為客戶提供網(wǎng)站設(shè)計(jì)、網(wǎng)站建設(shè) 網(wǎng)站設(shè)計(jì)制作定制網(wǎng)站,公司網(wǎng)站建設(shè),企業(yè)網(wǎng)站建設(shè),品牌網(wǎng)站制作,全網(wǎng)營(yíng)銷(xiāo)推廣,成都外貿(mào)網(wǎng)站建設(shè)公司,鐵鋒網(wǎng)站建設(shè)費(fèi)用合理。class LateInitExample {
lateinit var value:String
}
fun main() {
val example = LateInitExample()
// 如果沒(méi)有賦值就使用,直接拋出異常。
example.value = "lateinit example"
println("${example.value}")
}
2.lateinit的具體實(shí)現(xiàn)public class LateInitExample {
private String value;
public String getValue() {
// 如果沒(méi)有初始化過(guò),就拋出異常
if (value == null){
throw new RuntimeException("lateinit property value has not been initialized");
}
return value;
}
public void setValue(String value) {
// 這里要做非null檢查
this.value = value;
}
}
我們知道使用kotlin的屬性其實(shí)是在調(diào)用get和set方法,lateinit關(guān)鍵字其實(shí)就是對(duì)get和set方法做了一些操作。
注意lateinit不能修飾基本類型。
二、by lazyby 和 lazy要單獨(dú)拿出來(lái)看,不能當(dāng)做一個(gè)整體來(lái)看。
by:這里涉及到了kotlin的委托中委托屬性。
lazy:一個(gè)kotlin的函數(shù)
1.屬性委托簡(jiǎn)單通俗理解就是這個(gè)變量的get,set都是委托給了另外一個(gè)類來(lái)去操作。
如果是var變量,必須要有g(shù)etValue和setValue2個(gè)方法,val變量不需要setValue方法。
// 委托的類
class Delegate {
operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
return "$thisRef, 這里委托了 ${property.name} 屬性"
}
operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
println("$thisRef 的 ${property.name} 屬性賦值為 $value")
}
}
注意別和kotlin的get和set方法混淆了!!!!
語(yǔ)法是: val/var<屬性名>:<類型>by<表達(dá)式>
Kotlin 標(biāo)準(zhǔn)庫(kù)為幾種有用的委托提供了工廠方法,延遲屬性 Lazy就是其中之一。
https://www.runoob.com/kotlin/kotlin-delegated.html
2.lazy的實(shí)現(xiàn)public actual funlazy(lock: Any?, initializer: () ->T): Lazy= SynchronizedLazyImpl(initializer, lock)
private class SynchronizedLazyImpl(initializer: () ->T, lock: Any? = null) : Lazy, Serializable {
private var initializer: (() ->T)? = initializer
@Volatile private var _value: Any? = UNINITIALIZED_VALUE
// final field is required to enable safe publication of constructed instance
private val lock = lock ?: this
override val value: T
get() {
val _v1 = _value
if (_v1 !== UNINITIALIZED_VALUE) {
@Suppress("UNCHECKED_CAST")
return _v1 as T
}
return synchronized(lock) {
val _v2 = _value
if (_v2 !== UNINITIALIZED_VALUE) {
@Suppress("UNCHECKED_CAST") (_v2 as T)
} else {
val typedValue = initializer!!()
_value = typedValue
initializer = null
typedValue
}
}
}
override fun isInitialized(): Boolean = _value !== UNINITIALIZED_VALUE
override fun toString(): String = if (isInitialized()) value.toString() else "Lazy value not initialized yet."
private fun writeReplace(): Any = InitializedLazyImpl(value)
}
看到這里,相信大家只剩下一個(gè)疑惑了,為什么沒(méi)有g(shù)etValue方法,不是說(shuō)by的實(shí)現(xiàn)需要getValue方法嗎?這里,kotlin使用了擴(kuò)展函數(shù)來(lái)做。
// 這里返回value,就會(huì)執(zhí)行實(shí)現(xiàn)類的override value get了。
public inline operator funLazy.getValue(thisRef: Any?, property: KProperty<*>): T = value
三、總結(jié)從本質(zhì)上來(lái)說(shuō),lateinit和by lazy的區(qū)別是體現(xiàn)在內(nèi)存上:
lateinit修飾的屬性,會(huì)在內(nèi)存中創(chuàng)建,只不過(guò)沒(méi)有賦值
by lazy修飾的屬性,只有在使用的時(shí)候才會(huì)在內(nèi)存中創(chuàng)建
你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機(jī)房具備T級(jí)流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級(jí)服務(wù)器適合批量采購(gòu),新人活動(dòng)首月15元起,快前往官網(wǎng)查看詳情吧