lateinit

語法

不用一開始就要初始化變數,使用的時候,才初始化。

宣告一個非空(non-null)的變數,但不立即賦值,而是在之後的某個時間點再初始化。

使用時機:
用 lateinit:確定變數一定會被初始化,且只需要初始化一次

語法

private lateinit var 變數名: 類型

Android 的 ViewBinding

原本這樣寫會出錯,強迫一定要初始化

1
private var binding : ActivityMainBinding

在var前面加上lateinit延後初始化,就不用一開始就一定要初始化。

1
private lateinit var binding : ActivityMainBinding

沒加lateinit,又不設預設值,會編譯錯誤。

1
2
3
4
5
6
7
class MyActivity : AppCompatActivity() {
    // 編譯錯誤:必須在構造函式中初始化
    private var binding: ActivityMainBinding
    
    // 但這樣寫很醜,要用 null 和 !! 
    private var binding: ActivityMainBinding? = null
}

完整初始化程式碼

1
2
3
4
5
6
7
8
9
10
class MainActivity13 : AppCompatActivity() {
  // 延後初始化
  private lateinit var binding : ActivityMainBinding
  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    // 在這初始化
    binding = ActivityMainBinding.inflate(layoutInflater)
    setContentView(binding.root)
  }
}

類別成員變數

判斷是否有初始值

::變數.isInitialized
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class MyClass {
    lateinit var retrofit: String
    fun init() {
        retrofit = "retrofit is ready!"
    }

    fun use() {
        if (::retrofit.isInitialized) {
            println(retrofit)
        }
    }
}

fun main() {
    val myclass = MyClass()
    myclass.init()
    myclass.use()
}
retrofit is ready!

不能用 lateinit 的情況

基本類型不能用lateinit,會編譯錯誤。

1
2
3
    lateinit var count: Int
    lateinit var price: Double
    lateinit var isInit: Boolean

可空類型不能用lateinit

1
lateinit var name: String?

建構子也不能用lateinit

1
2
class MyClass(lateinit var name: String) {
}

可空類型 vs lateinit

可空類型,使用前要用 ? 或 .let{} 判斷是否為null。

1
2
3
4
5
6
7
8
9
10
class MyClass2() {
    var name: String? = null
    fun init() {
        name = "Bill"
    }

    fun use() {
        println(name?.length ?: 0)
    }
}

lateinit,使用時不用加 ?

1
2
3
4
5
6
7
8
9
10
class MyClass2() {
    lateinit var name: String
    fun init() {
        name = "Bill"
    }

    fun use() {
        println(name.length)
    }
}

results matching ""

    No results matching ""