【问题标题】:NullPointerException when accessing overriden val in abstract constructor在抽象构造函数中访问覆盖的 val 时出现 NullPointerException
【发布时间】:2011-01-16 04:35:18
【问题描述】:

考虑以下(简化的)示例:

abstract class Bar[T] {
    val f: PartialFunction[T, T]
    val default: PartialFunction[T, T] = { case x => x }
    val chained = f orElse default
}

class Foo extends Bar[Int] {
    val f: PartialFunction[Int, Int] = { case 1 => 2 }
}

然后看着它崩溃:

scala> val foo = new Foo
java.lang.NullPointerException
        at Bar.<init>(<console>:8)
        at Foo.<init>(<console>:6)
        at .<init>(<console>:7)
        at .<clinit>(<console>)
        at RequestResult$.<init>(<console>:9)
        at RequestResult$.<clinit>(<console>)
        at RequestResult$scala_repl_result(<console>)
        ....

但是,如果我们将chained 放在具体类中:

abstract class Bar[T] {
    val f: PartialFunction[T, T]
    val default: PartialFunction[T, T] = { case x => x }
}

class Foo extends Bar[Int] {
    val f: PartialFunction[Int, Int] = { case 1 => 2 }
    val chained = f orElse default
}

它按预期工作:

scala> val foo = new Foo
foo: Foo = Foo@16132c4

我不得不承认我完全不知道这里发生了什么。漏洞? (这是在 Scala 2.8.1 上。)

【问题讨论】:

标签: scala


【解决方案1】:

“为什么我的抽象或覆盖的 val 为空?” https://github.com/paulp/scala-faq/wiki/Initialization-Order

【讨论】:

  • A:链接现在是 404,B:有些人想避免懒惰的 vals
  • 链接现在是here,用链接回答是不好的做法。
【解决方案2】:

我的猜测:这是在编译时完成的优化。编译器识别出您在Bar 中覆盖了f。因此,Bar 的“构造函数”首先执行来自Foo 的东西——没有f! -- 以及然后Bar 定义中的内容。所以f在构造chained的时候是没有定义的。

我称之为错误。

【讨论】:

    猜你喜欢
    • 2014-11-17
    • 2018-03-15
    • 2013-04-30
    • 2013-06-05
    • 1970-01-01
    • 1970-01-01
    • 2010-09-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多