为什么这段代码抛出空指针异常

Why is this code throwing a null pointer exception

我正在尝试编写一个递归解析器组合器 class

import scala.util.parsing.combinator._
class MyParser extends RegexParsers {
  override val skipWhitespace = true
  val singleValue = "[\p{L}][\p{L}0-9_\*]*".r
  val expr : Parser[Any] = subExpr ~ rep("&" ~ subExpr | "|" ~ subExpr)
  val subExpr : Parser[Any] = singleValue | "(" ~ expr ~ ")"
} 

当我尝试实例化它时。它抛出空指针异常

val parser = new MyParser 

java.lang.NullPointerException
  ammonite.$sess.cmd8$MyParser.<init>(cmd8.sc:4)
  ammonite.$sess.cmd9$.<init>(cmd9.sc:1)
  ammonite.$sess.cmd9$.<clinit>(cmd9.sc)

我真的很不明白为什么。代码中绝对没有任何内容会在构造时导致空指针异常。不确定发生了什么

MyParser的两个成员,exprsubExpr,每次创建MyParser时都要初始化,但它们相互引用。它们按顺序求值,当求值 expr 时,subExpr 仍然设置为 null。这个问题的简化版本是:

class Bad {
    val one = two - 1
    val two = one + 1
}

您可能希望将 exprsubExpr 更改为方法(使用 def),以便在需要时才检索它们。

另见 FAQ: Why is my abstract or overridden val null?