抽象超类Scala中的断言创建NPE [英] Assertions in abstract superclass scala creating NPE

查看:84
本文介绍了抽象超类Scala中的断言创建NPE的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在REPL中输入以下代码

The following code, when entered in REPL

abstract class A { val aSet: Set[Int]; require(aSet.contains(3)) }

class B extends A { val aSet = Set(4,5,6) }

new B()

给出空值异常,而不是不变的失败。

gives a null point exception, rather than an invariant failure.

解决这个问题的最佳习惯是什么?

What would be the best idiom to solve this problem?

类似的问题:

代码合同:抽象类中的不变量

抽象类Scala中的私有构造函数

以及在线评论: https://gist.github.com/jkpl/4932e8730c1810261381851b13dfd29d

推荐答案

当您声明 val ,会发生几件事:

When you declare a val, several things happen:


  1. Th e编译器确保在初始化类的实例时为变量分配足够的空间

  2. 创建访问器方法

  3. 设置变量的初始值。

您的代码

abstract class A { val aSet: Set[Int]; require(aSet.contains(3)) }
class B extends A { val aSet = Set(4,5,6) }
new B()

大致等于

abstract class A { 
  private var aSet_A: Set[Int] = null
  def aSet: Set[Int] = aSet_A
  require(aSet.contains(3)) 
}

class B extends A {
  private var aSet_B: Set[Int] = Set(4,5,6) 
  override def aSet: Set[Int] = aSet_B
}

new B()

因此,发生以下情况:


  1. 分配了 aSet_A aSet_B 的内存并设置为 null

  2. 运行 A 的初始化程序。

  3. require aSet.contains(3)

  4. 由于 aSet B 中被覆盖,因此它返回 aSet_B

  5. 由于 aSet_B null (NPE)

  1. Memory for aSet_A and aSet_B is allocated and set to null.
  2. Initializer of A is run.
  3. require on aSet.contains(3) is invoked
  4. Since aSet is overridden in B, it returns aSet_B.
  5. Since aSet_B is null, an NPE is thrown.

到避免这种情况,您可以将 aSet 实现为惰性变量:

To avoid this, you can implement aSet as a lazy variable:

abstract class A { 
  def aSet: Set[Int]
  require(aSet.contains(3)) 
}

class B extends A {
  lazy val aSet = Set(4,5,6) 
}

new B()

这将引发要求失败例外:

java.lang.IllegalArgumentException: requirement failed






强制性链接到Scala的常见问题解答:


Obligatory link to Scala's FAQ:

  • Why is my abstract or overridden val null?

相关列表问题:



  1. 已覆盖值的父代码已运行,但未在父级分配值

  1. Why does implement abstract method using val and call from superclass in val expression return NullPointerException
  2. Overridden value parent code is run but value is not assigned at parent

这篇关于抽象超类Scala中的断言创建NPE的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆