Scala 对象的初始化是如何工作的?
How does initialisation of Scala objects work?
我是 运行 一个 sbt 应用程序实例化了一个 class MyObject
的对象,它使用来自其伴随对象的 val。这是主要的 class(object):
object MainClass {
def main(args: Array[String]) {
val a = new MyObject()
}
}
这里是MyObject
的定义:
import java.text.SimpleDateFormat
import java.util.Calendar
class MyObject {
val aValue = MyObject.yesterday
}
object MyObject {
val yesterday = getDaysAgo(1)
val dateNumFormat = new SimpleDateFormat("yyyymmdd")
private def getDaysAgo(n: Int) = {
val today = Calendar.getInstance()
today.add(Calendar.DAY_OF_MONTH, -n)
//println(dateNumFormat.format(today.getTime))
today.getTime
}
}
当我取消注释 println
语句时,我得到(确切的)以下错误:
$ sbt run
[info] Loading project definition from C:\Work\metaswitch\RandomProject\project
[info] Set current project to RandomProject (in build file:/C:/Work/metaswitch/RandomProject/)
[info] Compiling 1 Scala source to C:\Work\metaswitch\RandomProject\target\scala-2.11\classes...
[info] Running MainClass
[error] (run-main-0) java.lang.ExceptionInInitializerError
java.lang.ExceptionInInitializerError
at MyObject.<init>(MyObject.scala:21)
at MainClass$.main(MainClass.scala:6)
at MainClass.main(MainClass.scala)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
Caused by: java.lang.NullPointerException
at MyObject$.getDaysAgo(MyObject.scala:13)
at MyObject$.<init>(MyObject.scala:6)
at MyObject$.<clinit>(MyObject.scala)
at MyObject.<init>(MyObject.scala:21)
at MainClass$.main(MainClass.scala:6)
at MainClass.main(MainClass.scala)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
[trace] Stack trace suppressed: run last compile:run for the full output.
java.lang.RuntimeException: Nonzero exit code: 1
at scala.sys.package$.error(package.scala:27)
[trace] Stack trace suppressed: run last compile:run for the full output.
[error] (compile:run) Nonzero exit code: 1
[error] Total time: 2 s, completed 06-Jan-2016 11:21:16
字段的初始化按文本顺序进行(即,按顺序,字段在 class/object 中声明)。
鉴于代码中的声明顺序,首先声明 yesterday
,它将首先被初始化,从而调用 getDaysAgo
。该方法依次尝试读取(尚未初始化的)字段 dateNumFormat
,它产生 null
,导致表达式 dateNumFormat.format(today.getTime)
抛出 NullPointerException
。
最简单的解决方法是,将 dateNumFormat
的声明(和初始化)移到 yesterday
之前——正如您已经发现的那样。
我是 运行 一个 sbt 应用程序实例化了一个 class MyObject
的对象,它使用来自其伴随对象的 val。这是主要的 class(object):
object MainClass {
def main(args: Array[String]) {
val a = new MyObject()
}
}
这里是MyObject
的定义:
import java.text.SimpleDateFormat
import java.util.Calendar
class MyObject {
val aValue = MyObject.yesterday
}
object MyObject {
val yesterday = getDaysAgo(1)
val dateNumFormat = new SimpleDateFormat("yyyymmdd")
private def getDaysAgo(n: Int) = {
val today = Calendar.getInstance()
today.add(Calendar.DAY_OF_MONTH, -n)
//println(dateNumFormat.format(today.getTime))
today.getTime
}
}
当我取消注释 println
语句时,我得到(确切的)以下错误:
$ sbt run
[info] Loading project definition from C:\Work\metaswitch\RandomProject\project
[info] Set current project to RandomProject (in build file:/C:/Work/metaswitch/RandomProject/)
[info] Compiling 1 Scala source to C:\Work\metaswitch\RandomProject\target\scala-2.11\classes...
[info] Running MainClass
[error] (run-main-0) java.lang.ExceptionInInitializerError
java.lang.ExceptionInInitializerError
at MyObject.<init>(MyObject.scala:21)
at MainClass$.main(MainClass.scala:6)
at MainClass.main(MainClass.scala)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
Caused by: java.lang.NullPointerException
at MyObject$.getDaysAgo(MyObject.scala:13)
at MyObject$.<init>(MyObject.scala:6)
at MyObject$.<clinit>(MyObject.scala)
at MyObject.<init>(MyObject.scala:21)
at MainClass$.main(MainClass.scala:6)
at MainClass.main(MainClass.scala)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
[trace] Stack trace suppressed: run last compile:run for the full output.
java.lang.RuntimeException: Nonzero exit code: 1
at scala.sys.package$.error(package.scala:27)
[trace] Stack trace suppressed: run last compile:run for the full output.
[error] (compile:run) Nonzero exit code: 1
[error] Total time: 2 s, completed 06-Jan-2016 11:21:16
字段的初始化按文本顺序进行(即,按顺序,字段在 class/object 中声明)。
鉴于代码中的声明顺序,首先声明 yesterday
,它将首先被初始化,从而调用 getDaysAgo
。该方法依次尝试读取(尚未初始化的)字段 dateNumFormat
,它产生 null
,导致表达式 dateNumFormat.format(today.getTime)
抛出 NullPointerException
。
最简单的解决方法是,将 dateNumFormat
的声明(和初始化)移到 yesterday
之前——正如您已经发现的那样。