gpt4 book ai didi

kotlin - 顶级属性的初始化

转载 作者:行者123 更新时间:2023-12-05 04:26:00 24 4
gpt4 key购买 nike

我遇到了一些关于 kotlin 顶级属性的问题,下面是示例代码:

// Situation 1

class TreeNode(var `val`: Int) {
var left: TreeNode? = null
var right: TreeNode? = null
}

val tree2 = TreeNode(2)
val tree1 = TreeNode(3).apply { left = tree2 }

fun main() {
println(tree1.left) // prints "TreeNode@..."
}
// Situation 2

class TreeNode(var `val`: Int) {
var left: TreeNode? = null
var right: TreeNode? = null
}

val tree1 = TreeNode(3).apply { left = tree2 }
val tree2 = TreeNode(2)

fun main() {
println(tree1.left) // prints "null"
}
// Situation 3

class TreeNode(var `val`: Int) {
var left: TreeNode? = throw Exception("I am an exception")
var right: TreeNode? = null
}

val tree1 = TreeNode(3).apply { left = tree2 }
val tree2 = TreeNode(2)

fun main() {
/* prints "Exception in thread "main" java.lang.ExceptionInInitializerError
* Caused by: java.lang.Exception: I am an exception ..."
*/
println(tree1.left)
}

好像是

  1. 顶层属性从上到下初始化;
  2. 如果依赖的属性没有被初始化,将被替换为默认值;

我说的对吗?如果是,我想知道

  1. 是否有官方文件说明这种行为?
  2. 如果依赖属性尚未初始化,为什么更愿意将其替换为默认值,而不是出现编译时错误或抛出运行时错误说 tree2 未初始化?

谢谢!

最佳答案

top-level properties are initialized from top to bottom;

实际上,我在 Kotlin/Core 规范中找不到任何可以证实这一点的内容。我只能找到这个 Kotlin forum post这表示顶级属性初始化是平台相关的,并且您获得的唯一保证是属性的初始化程序将在您访问该属性之前运行,这并没有说明任何其他属性的初始化程序。

Kotlin doesn’t give you any guarantees when top level properties willbe initialized. All you can say is that the initialization code willbe called before you access a property, but you can’t necessariallytell when.

If you know which target platform you are on, you have a bit moreinformation. I don’t know enough about native to help you there but onthe JVM a top level property get’s initialized the when you call anytop level function or property within the file. It’s a bit morecomplicated than that. It has to do with the JVM classloader and whenthat calls static initialization blocks ( function).

不会说谎,这也让我感到惊讶!但从我的测试来看,目前的编译器版本 1.7.10 似乎确实在所有平台(JVM、JS、 native )上初始化顶级属性,除非它们是内联的。


if the depended property is not initialized, it will be replaced by the default value

这也不是真的。如果依赖属性没有被初始化,它得到的值是未指定。根据spec (强调我的):

The main difference between declaration scopes and statement scopes is that names in the statement scope are bound in the order of appearance. It is not allowed to access a value through an identifier in code which (syntactically) precedes the binding itself. On the contrary, in declaration scopes it is fully allowed, although initialization cycles may occur leading to unspecified behaviour.

非脚本 Kotlin 文件的顶级范围是“声明范围”,正如该页面前面指定的那样。


由于您似乎在 JVM 上,情况 2 中实际发生的(但未指定)是未初始化的 tree2null(所有引用类型的默认值在 JVM 上),并分配给 left,此时它也恰好是 null

对于情况 3,根本没有特定于平台的行为。您调用 Tree 的构造函数,然后运行 ​​left 的初始化程序,然后抛出异常,程序到此结束。它甚至没有到达 apply 部分。

充分证明未初始化属性的未指定行为是

fun main() {
println(y)
}

val y = run { x }
val x = run { 1 }

在 JVM 上,它打印 0。在 Kotlin/Native 上,它也打印 0,但我想它也可以打印恰好位于该位置的任何位。在 Kotlin/JS 上,它打印“undefined”。


至于为什么设计成“未指定”,大概是因为Kotlin团队还有其他更重要的事情要关注。无论如何,人们通常不会有太多相互依赖的全局属性。 See also this great answer by Eric Lippert.

关于kotlin - 顶级属性的初始化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73119406/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com