Kotlin主构造、次构造、init的执行顺序

2,666 阅读2分钟

背景

Kotlin有主构造函数、次构造函数和init,他们的执行顺序是什么?

查看它们的执行顺序,最好的方法还是以打印为主。创建一个类,内部有主构造、次构造和一个init。

class Test {
    constructor(name:String){
        println("主构造函数")
    }

    constructor(name:String ,age:Int):this(name){
        println("次构造函数")
    }

    init {
        println("init....")
    }  
}

测试的时候,执行Test("Kt",0),我们看看执行打印。

image.png

结论

执行顺序: init -> 主构造函数 -> 次构造函数

为什么?

如果我答对了上面的问题,那么接下来面试官就会继续追问:

“为什么在Kotlin中,构造函数的执行顺序是init -> 主构造函数 -> 次构造函数?”

这个问题就需要去反编译为字节码,看看内部的流程是如何处理的。

#反编译

image.png

从上图看显而易见,当我们执行Test("Kt",0)时,会执行到次构造函数,但从次构造函数反编译的代码来看,会先执行this(name),指代的也就是主构造函数。而在主构造函数中,先会执行init,而后执行主构造函数内部的方法。

再加一个伴生对象呢?

如果你答出了以上两个问题,那么面试官还会继续追问:

“如果加上伴生对象,执行顺序又会是什么?为什么?“

实践出真知,在原有的测试代码上加上伴生对象。

companion object{
    init {
        println("伴生对象init")
    }
}

依然先看下结论。

image.png

结论

执行顺序:伴生对象 -> init -> 主构造函数 -> 次构造函数

为什么?

#反编译

image.png 从上图可以看到,伴生对象被反编译后,其实是多了一个static final的内部类,而被static修饰执行是优先于普通代码块。

推荐阅读

原来,协程是这么挂起的!

差异化分析,let,run,with,apply及also