什么是Kotlin类初始化语义?

我一直无法在解释Kotlin中一个类的初始化的语言定义中找到任何东西。

import java.util.Properties fun main(args: Array<String>) { val out = MyClass() out.fn() } class MyClass { private val a = Properties() // 1 init { fn() } public fun fn() { println("Fn called. a = $a") } // private val a = Properties() // 2 } 

运行这个程序的结果会根据属性是在(1)还是在(2)初始化而改变。

我很惊讶宣言的顺序与语言有关,并希望了解这背后的决定。 我的期望是在调用构造函数体之前初始化属性。

我的期望是在调用构造函数体之前初始化属性。

那么, init块不是一个构造函数 。 它是一个不同的结构,它允许你执行对象的初始化,并且它们[init块]以声明顺序与属性初始值设定项执行。

构造函数是一个不同的野兽蚂蚁,它们在所有属性初始化并执行完所有init块后执行。 看下面的例子:

 class A(val value: Int) { constructor(): this(0) { println("Constructor") } init { println("Init block") } } fun main(args: Array<String>) { val a = A() } 

输出是:

 Init block Constructor 

你可以把init块放在任何你想要的地方:在constructor之前或之后; 它将始终在A的构造函数之前执行(在本例中为次构造函数)。

简单地说:创建类的实例时,(几乎)首先运行父类(如果存在)的构造函数,然后运行主构造函数。

主构造函数执行从上到下在类体中声明的代码。 这些名字也可以通过相同的规则获得:

 class Foo(a: String = "might be first" val b: String = "second" + a) : Boo(a + b + "third"){ var c = a + "fourth" + b init {print("fifth: $c")} val d = "sixth" init {print("seventh: the end of the primary constructor"} } 

如果你调用一个辅助构造函数,那么它在主链之后工作,因为它是在链中构成的(类似于调用父构造函数)。