【问题标题】:Scala initialisation order (using scalatest)Scala 初始化顺序(使用 scalatest)
【发布时间】:2015-05-19 22:58:30
【问题描述】:

如果有人能向我解释为什么以下会导致问题,我将不胜感激。我创建了一个小例子来演示这个问题:

我有一个正在用 sbt 构建的项目,build.sbt 如下:

lazy val root = (project in file(".")).
    settings(
        name := "Test",
        version := "1.0.0",
        scalaVersion := "2.11.5",
        libraryDependencies += "org.scalatest" %% "scalatest" % "2.2.4" % Test
    )

和 src/main/scala 中的 Test.scala:

object Test extends App
{
    private val map = Map(1 -> 2)
    def access = map(1)

    println(access)
}

和 src/test/scala 中的 TestSpec.scala(使用 scalatest):

import org.scalatest.FlatSpec

class TestSpec extends FlatSpec
{
    "A Test" should "allow access to the map" in
    {
        assert(Test.access == 2)
    }
}

如果我 sbt run 则 '2' 会按预期打印出来。如果我 sbt test 然后我得到一个 NullPointerException 并且测试失败:

[info] TestSpec:
[info] A Test
[info] - should allow access to the map *** FAILED ***
[info]   java.lang.NullPointerException:
[info]   at Test$.access(Test.scala:4)
[info]   at TestSpec$$anonfun$1.apply$mcV$sp(TestSpec.scala:7)
etc.

这是因为在 TestSpec 访问时 map 为空。我可以通过将地图更改为惰性 val 或 def 来解决此问题,但我想了解更多关于此处的初始化顺序发生了什么以及将来如何避免此类事情的详细信息。如果我尝试使用 src\main\scala 中的另一个源文件访问它,我没有任何问题,并且我想避免以这种方式更改变量的定义来解决此类问题。

谢谢

【问题讨论】:

    标签: scala sbt scalatest


    【解决方案1】:

    我不知道答案,但研究它很有趣。

    显然特质App有点特殊

    http://www.scala-lang.org/api/current/index.html#scala.App

    需要注意的是,这个 trait 是使用 DelayedInit 功能,这意味着对象的字段将 在 main 方法执行之前没有被初始化。

    【讨论】:

    • 这就是答案! :) 取消 App 并定义一个明确的 main 解决了这个问题。我想从现在开始我会避免使用 App,除非我只是在一个对象中玩弄某些东西。谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-02-07
    • 1970-01-01
    • 2010-09-17
    • 1970-01-01
    • 2011-10-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多