得出结论
伴生对象 > 初始化代码块 > 构造函数
(先>后)
代码验证
/**
* @data on 4/1/21 12:27 AM
* @auther KC
* @describe 探究Kotlin的init{}、构造方法、伴生对象执行顺序
*/
class Coffee(val tease:String,val price:Double) {
//初始化代码块
init {
println("init1")
}
init {
println("init2")
}
//次构造函数
constructor(tease:String) : this("bad",15.8){
println("constructor")
}
//伴生对象
companion object {
val flag = false
fun plus(num1:Int,num2:Int):Int {
return num1+num2
}
init {
println("companion object init1")
}
init {
println("companion object init2")
}
}
}
//主方法验证
fun main(args:Array<String>){
val coffe = Coffee("e") //用于验证
/**
* 验证结果:先后排序
* companion object init1
* companion object init2
* init1
* init2
* constructor
* 总结:伴生对象 > 初始化代码块 > 构造函数 (先>后)
*/
// val coffee = Coffee("good",9.9) //正常对象创建
// println(Coffee.flag) //用于验证伴生对象调用
// println(Coffee.plus(1,1)) //用于验证伴生对象调用
}
伴生对象的作用
通过的 Coffee.plus(1, 2) 和 Coffee.flag 代码不难看出来,类似于 Java 中使用类访问静态成员的语法。因为 Kotlin 取消了 static 关键字,所以 Kotlin 引入伴生对象来弥补没有静态成员的不足。可见,伴生对象的主要作用就是为其所在的外部类模拟静态成员。
init{}代码块
init块和属性的初始化是平级的,按代码顺序执行。
与Java中的对比异同
kotlin的伴生对象(companion object)相当于java中的静态初始化块(static {}), 只被同个类的所有实例的第一个实例执行一次, 用于静态成员变量初始化和初始化代码。
kotlin的init代码块(init {})相当于java的非静态初始化块({}), 每个类实例都会执行, 且按先后顺序执行, 用于对多个构造函数的代码复用。
kotlin的主构造函数, 在java中没有, 比次构造函数(constructor)先执行 (从次构造函数需要继承 : this()主构造函数已经可以推测是主构造函数先执行), 每个类实例都会执行, 用于类成员变量的声明/赋值, 由于没有代码块, 所以不能做其他初始化逻辑。
kotlin的次构造函数(constructor)相当于java的构造函数, 函数签名要跟主构造函数不一样, 否则报错, 可以重载出多个次构造函数, 用于类初始化, 由于有代码块, 所以可以做其他初始化逻辑。