为什么没有属性初始化器调用一个自定义的setter?

从Kotlin文档中 ,允许自定义setter:

class Test { var stringRepresentation: String get() = field set(value) { setDataFromString(value) } init { stringRepresentation = "test" } private fun setDataFromString(value: String) { } } 

但是你不能没有一个自定义getter的自定义setter(并从init块初始化):

 class Test { // Compilation error: "Property must be initialized" var stringRepresentation: String set(value) { setDataFromString(value) } init { stringRepresentation = "test" } private fun setDataFromString(value: String) { } } 

虽然你可以有一个自定义的getter没有自定义setter,没有问题在这里:

 class Test { var stringRepresentation: String get() = field init { stringRepresentation = "test" } private fun setDataFromString(value: String) { } } 

那么为什么你不能使用一个自定义的setter来初始化从init块中的属性,为什么init块会在属性初始值设定项直接分配的时候调用自定义的setter,绕过自定义的setter?

 class Test { var stringRepresentation: String = "" // Does not call custom setter set(value) { setDataFromString(value) } init { stringRepresentation = "test" // Calls custom setter } private fun setDataFromString(value: String) { } } 

属性初始值设定项不会调用自定义设置项,因为它们的目的是提供默认值。

与Java不同,在Kotlin中,不仅局部变量必须在第一次访问之前被初始化,但是类属性也必须被初始化。

在Java中这是有效的。

 public class Test { public String str; public static void main(String[] args) { System.out.println(new Test().str); } } 

在Kotlin这不是。

 class Parent { var str: String? } fun main(args: Array<String>) { Parent().str } 

由于这个原因,自定义设置器需要通过属性初始值设定项或构造函数来初始化其属性。 看看下面的例子。

 class Test { var stringRepresentation: String = "a" // Default value. Does not call custom setter get() = field set(value) { println("Setting stringRepresentation property to %s. Current value is %s.".format(value, field)) field = setDataFromString(value) } init { this.stringRepresentation = "b" // Calls custom setter } private fun setDataFromString(value: String): String { println("Setting stringRepresentation property to %s.".format(value)) return value } } fun main(args: Array<String>) { Test().stringRepresentation = "c" // Calls custom setter } 

属性stringRepresentation被初始化为其”的 opon实例,而不调用setter。 然后调用init块,并使用setter将值设置为“b” 。 然后用 setter “c”