kotlin的主構造函數, 次構造函數, init代碼塊, 伴生對象的執行順序, 特點, 使用場景, 及跟java的比較
目錄
kotlin的主構造函數, 次構造函數, init代碼塊, 伴生對象的執行順序, 特點, 使用場景, 及跟java的比較
測試代碼1:
class Person(var from: String) {
/*屬性from*/
//已經在主構造函數中聲明 private var from: String = ""
/*次構造方法*/
constructor(from1: String, name: String) : this(from1) {
println("constructor, from:$from1\n")
}
companion object {
val instance = Person("companion")
/*伴生對象中的初始化代碼*/
init {
println("companion init 1\n")
}
init {
println("companion init 2\n")
}
/* 伴生對象中不允許有構造函數
constructor() {
println("companion constructor\n")
} */
}
/*初始化代碼塊*/
init {
println("init 2, from:${from}\n")
}
/*初始化代碼塊*/
init {
println("init 1, from:${from}\n")
}
}
fun main(args: Array<String>) {
println("調用次構造方法:\n")
Person("main1", "name1")
println("\n\n調用主構造方法:\n")
Person("main2")
}
結果1:
調用次構造方法:
init 2, from:companion
init 1, from:companion
companion init 1
companion init 2
init 2, from:main1
init 1, from:main1
constructor, from:main1
調用主構造方法:
init 2, from:main2
init 1, from:main2
測試代碼2:
如果把main函數改成:
fun main(args: Array<String>) {
println("\n\n調用主構造方法:\n")
Person("main2")
println("\n\n調用次構造方法:\n")
Person("main1", "name1")
}
結果2:
調用主構造方法:
init 2, from:companion
init 1, from:companion
companion init 1
companion init 2
init 2, from:main2
init 1, from:main2
調用次構造方法:
init 2, from:main1
init 1, from:main1
constructor, from:main1
結論--執行順序:
1. 伴生對象中成員變量初始化
2. 伴生對象中init代碼塊按先後順序執行
3. 類的init代碼塊按先後順序執行
4. 類的主構造函數
5. 類的次構造函數
結論--跟java的比較, 特點, 使用場景:
1. kotlin的伴生對象(companion object)相當於java中的靜態初始化塊(static {}), 只被同個類的所有實例的第一個實例執行一次, 用於靜態成員變量初始化和初始化代碼
2. kotlin的init代碼塊(init {})相當於java的非靜態初始化塊({}), 每個類實例都會執行, 且按先後順序執行, 用於對多個構造函數的代碼複用
3. kotlin的主構造函數, 在java中沒有, 比次構造函數(constructor)先執行 (從次構造函數需要繼承 : this()主構造函數已經可以推測是主構造函數先執行), 每個類實例都會執行, 用於類成員變量的聲明/賦值, 由於沒有代碼塊, 所以不能做其他初始化邏輯
4. kotlin的次構造函數(constructor)相當於java的構造函數, 函數簽名要跟主構造函數不一樣, 否則報錯, 可以重載出多個次構造函數, 用於類初始化, 由於有代碼塊, 所以可以做其他初始化邏輯
Java的初始化塊、靜態初始化塊、構造函數的執行順序及用途
https://blog.csdn.net/guyue35/article/details/105094901