当前位置: 首页 > 知识库问答 >
问题:

为什么Kotlin编译器需要var属性的显式初始化器?

洪昱
2023-03-14

我无法理解以下科特林文档:

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 字段(具有默认值)之间有什么区别,这不允许我们有属性的默认值?

共有2个答案

万修为
2023-03-14

静态编程语言不会做任何隐式操作。它不会在没有您的特定指令的情况下转换数字类型,也不会在没有明确说明的情况下设置默认值或初始化值。它是一种设计选择,旨在消除在典型Java程序中发现的常见错误。编译器不清楚您是否忘记初始化它,或者您是否打算使用默认值。因为不清楚,所以很糟糕。因此可能会导致错误。

静态编程语言的设计选择有助于消除代码中的错误,编译器无法帮助确定是否存在错误。它在语言中是哲学的和一致的。

Kotlin在使用前需要初始化。对于意味着构造函数和初始值设定项完成时的成员,它必须具有值<var上的code>lateinitmodifier允许在编译时忽略这一点,尽管在运行时,当您访问变量时会进行检查。对于局部变量,任何代码分支都必须在访问前初始化值。例如:

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")
    }
}
仲孙默
2023-03-14

这很简单:在Java中,默认值为0(零)和值。但在 Kotlin 中,大多数值都不能为空,因此您无法用 null 初始化它们。对于基元值,可能存在使用零初始化的默认策略,但为了保持一致,这样做并不是如此。但在基元数组中,默认值确实为零。

如果您真的需要初始化语义,请查看lateinit属性:https://kotlinlang.org/docs/reference/properties.html#late-initialized-properties.

该机制基本上允许使用null初始化一个字段,但随后将您从空断言中解放出来。

附加

实际上,Kotlin在初始化方面非常聪明。例如:

val x: Int

if(something)
    x = 1
else
    x = 2

println(x)

在这里,kotlinc可以证明x在被使用之前被初始化,所以代码是可以的。

 类似资料:
  • 本文向大家介绍为什么要初始化 CSS 样式相关面试题,主要包含被问及为什么要初始化 CSS 样式时的应答技巧和注意事项,需要的朋友参考一下 因为浏览器的兼容问题,不同浏览器对有些标签的默认值是不同的,如果没对 CSS 初始化往往会出现浏览器之间的页面显示差异。 当然,初始化样式会对 SEO 有一定的影响,但鱼和熊掌不可兼得,但力求影响最小的情况下初始化。 最简单的初始化方法是:*{padding:

  • 我有这个密码: 这给我留下了编译器对我大喊大叫: 我花了很长时间才明白我必须改变Vec 代码现在编译,但我完全不明白这里到底有什么问题。为什么要在Vec定义中发送代码?我的意思是,这个特性已经实现了发送克隆。对我来说,这看起来相当多余。 有人能和我分享他的智慧吗,为什么我必须这样修改代码?

  • 我使用android Studio制作了一个静态编程语言MultiPlatform Mobile项目,导入SQLDelight后遇到以下错误: 我回答了这个问题,但他们提到的一切我都做对了。在一个文件一个文件地查看之后,我没有找到我在哪里声明了那个版本,于是我决定将我的项目与其中一个示例项目进行比较。 再次查看这些文件后,我发现我在我的应用程序等级中使用了SQLDelightVersion1.5.

  • 问题内容: 我有一个Swift类,我想看起来像这样: 但是,Swift不喜欢我要传递给初始化程序的事实。我在这里打破某些模式吗?应该如何完成这样的初始化? 问题答案: 您已经找到了Implicitly Unwrapped Optional 的主要用例。 你需要访问的,之前被初始化。 否则,应该 永远 是零,所以你不应该有外部的检查。 因此,您应该声明。

  • 问题内容: print语句导致以下编译时错误, 局部变量f可能尚未初始化 如果Java中的原语已经具有默认值(float = 0.0f) ,为什么需要定义一个? 所以这有效 感谢大家! 问题答案: 因为它是一个局部变量。这就是为什么什么都没有分配的原因: 局部变量略有不同。编译器永远不会为未初始化的局部变量分配默认值。如果您无法在声明它的地方初始化本地变量,请确保在尝试使用它之前为其分配一个值。访