这是我的测试代码:
class Test {
init {
a = 1
}
constructor() {
a = 2
}
private var a: Int
init {
a = 3
}
}
如果我删除了辅助构造函数:
class Test {
init {
a = 1 // Error: Variable cannot be initialized before declaration
}
// constructor() {
// a = 2
// }
private var a: Int
init {
a = 3
}
}
我知道
在实例初始化期间,初始化程序块的执行顺序与它们在类主体中的显示顺序相同。
但是,如果存在辅助构造函数,为什么我可以在声明之前初始化变量?
更新
我发现了一件有趣的事情:
class Test {
init {
a = log(1)
}
constructor() {
a = log(2)
}
private var a: Int = log(0)
init {
a = log(3)
}
}
fun log(i: Int): Int {
println(i)
return i
}
fun main(args: Array<String>) {
Test()
}
输出是:1 0 3 2
,这与Java相同,声明和初始化是两个不同的步骤,但对于Kotlin的主要构造函数来说这是奇怪的,呃......
答案 0 :(得分:1)
从我的观点来看,它不是与kotlin有关,而是与JVM字节码有关,它实际上没有变量的“初始化”,它只是在构造函数中填充它们,你可以用一些反编译器检查它。
答案 1 :(得分:1)
这是从迈克尔的评论中扩展而来,该评论引用了Kotlin documentation:
请注意,初始化程序块中的代码有效地成为主构造函数的一部分。对主构造函数的委派作为辅助构造函数的第一个语句发生,因此所有初始化程序块中的代码在辅助构造函数体之前执行。即使该类没有主构造函数,委托仍然会隐式发生,并且仍然会执行初始化程序块。
换句话说,init()
块与(隐式)主构造函数关联,该构造函数作为辅助构造函数的第一行执行。 -kf
答案 2 :(得分:0)
您的示例看起来有点不一致。它是由一个事实引起的,第一个例子没有主要构造函数,但第二个例子有一个。但是,https://youtrack.jetbrains.com/issue/KT-22317已创建。