2016-08-04 194 views
19

在Kotlin語言中,我們默認情況下必須在引入每個變量時對其進行初始化。爲了避免這種情況,可以使用lateinit關鍵字。在初始化之前參考lateinit變量會導致運行時異常。爲什麼Kotlin不允許使用基本類型的lateinit?

lateinit但是,不能與原始類型一起使用。爲什麼這樣?

回答

16

對於對象類型,科特林使用null值來標記一個lateinit屬性尚未初始化,並拋出適當的異常時財產被訪問。

對於原始類型,沒有這樣的值,因此無法將屬性標記爲未初始化並提供需要提供的診斷。 (我們可以嘗試使用某種單獨的標記,但通過反射來初始化字段時,該標記不會被更新,這是一個主要的用例lateinit)。

因此,lateinit僅支持對象類型的屬性。

+31

您能否在答案中澄清,爲什麼'lateinit Int'不能用'Integer'類型在運行時表示,它能夠在未初始化時保存'null'值? – Ilya

+0

@Ilya因爲'Integer'不是'int'。它是一種盒裝類型,在本地或通過反射設置東西時很重要。 –

+2

因此,我認爲Kotlin將原始類型包裝爲對象(例如int爲Int)。但是,爲什麼不能將Int保留爲空,因爲它是一個對象?另外,爲什麼我們不能將一個參數聲明爲可爲空並且將其延遲? (var x:Int?) – Yao

1

一個簡短的答案是,對於基元,您始終可以使用0作爲默認值,並且可以使用可爲空的類型null作爲默認值。只有不可空的非原始類型可能需要lateinit來解決類型安全系統。

實際上,沒有必要,只要它有一個值初始化之前在科特林變量中的第一訪問,它可以是靜態證明。這意味着該代碼是完全合法:

fun main(args: Array<String>) { 
    var x: Int 
    val y: Double 

    x = 0 
    y = x + 0.1 

    println("$x, $y") 
} 

但也有(罕見)情況下,當初始化不能靜態地證明。最常見的情況是使用任何形式的依賴注入的一類字段:

class Window { 
    @Inject lateinit parent: Parent 
} 
相關問題