为什么Kotlin编译器需要var属性的显式初始化器?
我无法理解以下Kotlin文档:
The initializer, getter and setter are optional. Property type is optional if it can be inferred from the initializer or from the base class member being overridden. Examples: var allByDefault: Int? // error: explicit initializer required, default getter and setter implied
为什么编译器需要显式初始化器(至少是我能想到的唯一解释)的唯一解释是Kotlin没有默认的属性值。 这样对吗? 如果是这样,为什么? 换句话说:Kotlin属性和Java字段(具有默认值)之间的区别是什么?它们不允许我们使用属性的默认值?
这很简单:在Java中,默认值是0
(零)和null
。 但是在Kotlin中,大部分的值都是不可空的,所以你不能用null
初始化它们。 对于原始值,可能会有一个用零初始化的默认策略,但是为了保持一致,没有这样做。 但是在原始数组中,默认值是零。
如果您确实需要初始化语义,请查看lateinit
属性: https : lateinit
。
该机制基本上允许用null
初始化一个字段,然后将你从null断言中解放出来。
加成
其实Kotlin对于初始化非常聪明。 例如,它的作品:
val x: Int if(something) x = 1 else x = 2 println(x)
这里kotlinc可以证明x
正在使用之前被初始化,所以代码是OK的
Kotlin没有做任何暗示。 它不会在没有特定指令的情况下转换数字类型,也不会在不明确的情况下设置默认值或初始化值。 这是消除常见Java程序中常见错误的设计选择。 对于编译器来说,如果你忘记初始化它,或者如果你想要使用一个默认值的话,这是不清楚的。 既然不清楚,那就不好了。 因此可能导致错误。
Kotlin的设计选择有助于消除由于编译器无法确定是否存在错误的代码而导致的错误。 这是语言上的哲学和一致的。
Kotlin在使用之前需要初始化。 对于在构造函数和初始化方法完成时意味着它的成员,它必须有一个值。 var
上的lateinit
修饰符允许在编译时忽略这一点,尽管在运行时检查是在访问变量时完成的。 对于本地变量,任何代码分支都必须在访问之前对值进行初始化。 例如:
fun stateFromAbbreviation(abbreviation: String?): String { val state: String if (abbreviation == null) { state = DEFAULT_STATE } else { state = stateMap.get(abbreviation) ?: throw IllegalStateException("Invalid state abbreviation $abbreviation") } return state }
这里局部变量可以在if
语句中初始化,假设所有的分支都初始化这个值。 但是,实际上,这个代码会更加习惯用if
作为表达式,比如:
fun stateFromAbbreviation(abbreviation: String?): String { return if (abbreviation == null) { DEFAULT_STATE } else { stateMap.get(abbreviation) ?: throw IllegalStateException("Invalid state abbreviation $abbreviation") } }