为什么当我进行单元测试时,我得到的覆盖点是 `final lazy val` 而不是 `final val`?

Why when I unit test do I get coverage points with `final lazy val` but not `final val`?

我有一些代码(此处提供项目源 - https://github.com/natemurthy/testing-final-vals):

object Main extends App {
  final val NAME = "foo"
}

我正在使用 ScalaTest 和 SBT Coverage 插件来测试这段代码,如下所示:

import org.scalatest.{FlatSpec,Matchers}

class MainTest extends FlatSpec with Matchers {
  it should "have a name" in {
    Main.NAME shouldBe "foo"
  }
}

但出于某种原因,只有当我在此表达式中包含 lazy 修饰符时,我才会获得覆盖点:

为什么会这样?

我的猜测是覆盖工具计算了执行的行数。

final val NAME = "foo"被编译为字节码中的常量内联值,如Java中的private static final。访问变量时,您只需从字节码常量中读取值。 More Info on inlining constant values during compiling

另一方面,

final lazy val NAME = "foo"编译成惰性构造方法,因为 JVM 中没有惰性值。如果您访问此变量,则会执行惰性构造方法。 More info on scala lazy value bytecode generation