【譯】kotlin中lateinit和by lazy的區別

原文內容來自 Kotlin - Property initialization using 「by lazy」 vs. 「lateinit」html

lazy { ... } delegate can only be used for val properties, whereas lateinit can only be applied to vars, because it can't be compiled to a final field, thus no immutability can be guaranteed;java

  • lazy { ... }只能被用在被val修飾的變量上,而lateinit只能被用var修飾的變量上,由於被lateinit修飾的字段沒法被編譯爲一個final字段、所以沒法保證它的不可變性。

lateinit var has a backing field which stores the value, and by lazy { ... } creates a delegate object in which the value is stored once calculated, stores the reference to the delegate instance in the class object and generates the getter for the property that works with the delegate instance. So if you need the backing field present in the class, use lateinitios

  • lateinit修飾的變量有一個幕後字段用來存儲它的值,而by lazy { ... }建立了一個包含by lazy { ... }中代碼返回值的實例對象,實例對象持有這個值並生成一個能夠在實例對象中調用的這個值的getter。因此若是你須要在代碼中使用幕後字段的話,使用lateinit

In addition to vals, lateinit cannot be used for nullable properties and Java primitive types (this is because of null used for uninitialized value)api

  • 除了被val修飾的變量外,lateinit也不能被用來修飾可空的屬性和java的基本類型(由於對於可空類型,會有默認值null

lateinit var can be initialized from anywhere the object is seen from, e.g. from inside a framework code, and multiple initialization scenarios are possible for different objects of a single class. by lazy { ... }, in turn, defines the only initializer for the property, which can be altered only by overriding the property in a subclass. If you want your property to be initialized from outside in a way probably unknown beforehand, use lateinit安全

  • lateinit修飾的變量能夠在對象(代碼)的任何地方進行初始化,並且同一個類的不一樣對象能夠對這個變量進行屢次的初始化(賦值)。可是,對於by lazy { ... }修飾的變量,只擁有惟一一個聲明在{}中的初始化構造器,若是你想要修改它,你只能經過在子類中覆寫的方式來修改它的值。因此,若是你想要你的屬性在其餘地方以不是你事先定義好的值初始化的話,使用lateinit

Initialization by lazy { ... } is thread-safe by default and guarantees that the initializer is invoked at most once (but this can be altered by using another lazy overload). In case of lateinit var, it's up to the user's code to initialize the property correctly in multi-threaded environments.閉包

  • by lazy { ... }的初始化默認是線程安全的,而且能保證by lazy { ... }代碼塊中的代碼最多被調用一次。而lateinit var默認是不保證線程安全的,它的狀況徹底取決於使用者的代碼。

A Lazy instance can be saved, passed around and even used for multiple properties. On contrary, lateinit vars do not store any additional runtime state (only null in the field for uninitialized value).app

  • Lazy實例是有值的,這個值能夠被存儲、傳遞和使用。可是,被lateinit var修飾的變量不存儲任何多餘的運行時狀態,只有值還未被初始化的null值。

If you hold a reference to an instance of LazyisInitialized() allows you to check whether it has already been initialized (and you can obtain such instance with reflection from a delegated property). To check whether a lateinit property has been initialized, you can use property::isInitialized since Kotlin 1.2.jvm

  • 若是你持有一個Lazy實例的引用,你可使用它的isInitialized()方法來判斷它是否已經被初始化。從Kotlin1.2開始,你也可使用方法引用的方式來獲取這個值。

A lambda passed to by lazy { ... } may capture references from the context where it is used into its closure.. It will then store the references and release them only once the property has been initialized. This may lead to object hierarchies, such as Android activities, not being released for too long (or ever, if the property remains accessible and is never accessed), so you should be careful about what you use inside the initializer lambda.ide

  • by lazy { ... }中傳遞的lambda表達式可能會捕獲它的閉包中使用的上下文的引用,引用會一直被持有直到變量被初始化。所以這樣可能會致使內存泄漏,因此仔細考慮你在lambda表達式中使用的值是否合理
相關文章
相關標籤/搜索