gpt4 book ai didi

Scala 对象初始化错误

转载 作者:行者123 更新时间:2023-12-02 01:21:58 29 4
gpt4 key购买 nike

我在 scala 中发现了“手写枚举”初始化的错误。它是手写的,因为它是 sealed case classobject SomeCode 里面有对象。

有趣的是 - 如果 sealed case class 有默认值 - 一些黑魔法就会发生。例如,我们有如下所示的“手写枚举”:

sealed case class SomeCode(
id: String,
legend: String)

object SomeCode {

object First extends SomeCode(id = "First", legend = "first legend")
object Second extends SomeCode(id = "Second", legend = "second legend")

val values = Seq(
SomeCode.First,
SomeCode.Second)

private val CACHE: Map[String, SomeCode] = {
val ids = values.map(_.id)
(ids zip values).toMap
}

def getById(id: String): Option[SomeCode] = CACHE.get(id)
}

还有一个测试:

import com.blabla.SomeCode
import org.scalatest.{Matchers, WordSpec}

class SomeCodeTest extends WordSpec with Matchers {
"SomeCode" should {
"work properly" in {
println(SomeCode.First.toString)
}
}
}

当我们调用 SomeCode.Fist 时,object SomeCode 的初始化开始。因此 val valuesprivate val CACHE 的初始化也开始了,实际上一切正常。

但是,如果我们为我们的密封案例类引入默认值...:

sealed case class SomeCode(
id: String,
legend: String = "default legend")
...
object First extends SomeCode(id = "First")
object Second extends SomeCode(id = "Second")

现在运行我们的测试 - 我们将在 CACHE 中拥有 NPE。

在测试中我们调用 SomeCode.First - 这个值在 values 中将为 null,所以 values.map(_ .id) 将抛出 NPE。如果从测试中我们将调用 SomeCode.Second 那么 null 将在 SomeCode.Second

我知道扩展 sealed case class 不是一个好习惯,但它应该可以正常工作。也许我不了解 scala 中的某些内容,但目前对我来说它看起来像是一个编译器错误。

scalaVersion := "2.11.7"

我还在 scala-lang 中创建问题:https://issues.scala-lang.org/browse/SI-9929

最佳答案

问题的发生是因为当我们调用 SomeCode.First.toString 时,SomeCode.First 在下面以 null 结尾代码:

val values = Seq(SomeCode.First, SomeCode.Second)

您可以通过在 REPL 中打印值的输出来检查以上内容是否属实。

有趣的是,使用以下代码查看 REPL 输出:

sealed case class SomeCode(
id: String,
legend: String = "default")

object SomeCode {
println("begin object init")
object First extends SomeCode(id = "First"){println("initializing First")}
object Second extends SomeCode(id = "Second"){println("initializing Second")}
println(SomeCode.First)
println(SomeCode.Second)
}

SomeCode.First

// REPL Output:
begin object init
null <--- SomeCode.First is null!!! Why does it not initialize the First object?
initializing Second <--- Correctly initializes the Second object.
SomeCode(Second,default)
initializing First <--- Now starts to initialize the First object
res41: SomeCode.First.type = SomeCode(First,default)

关于Scala 对象初始化错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39569936/

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