0

怎么了?为什么人是空的?

import org.scalacheck.{Arbitrary, Properties, Gen, Prop}
import Gen._
import Prop._

case class Person(name: String) {}

object QuickCheckPerson extends Properties("Person") {
  property("gen1") = forAll { (person: Person) =>
    println("person: " + person)
    person.name == "john"   // nullPointerException, because person == null
  }

  val john = Person("john")
  implicit lazy val arbPerson: Arbitrary[Person] = Arbitrary(value(john))
}

QuickCheckPerson.check

它因 NullPointerException 而失败。

但是,如果我val john = Person("john")property("gen1") = ....

为什么??

更新

如果我声明val johnas ,则该示例有效lazy。所以,似乎在lazy val arbPerson之前执行val john,但如果是这样,scala 编译器应该会失败,说john没有定义。john是 a val,也不是 a var,所以要么声明并实例化它,要么不声明。

对此有任何想法吗?

ps:斯卡拉2.10.3

4

1 回答 1

1

因此,似乎惰性 val arbPerson 在 val john 之前执行,但如果是这样,scala 编译器应该会失败,说 john 没有定义。john 是一个 val,也不是一个 var,所以要么声明并实例化它,要么不声明它。

不,这是不正确的。arbPerson是一个内部方法,它执行双重检查锁并懒惰地初始化一个私有字段。由于它是一种方法,因此可以从任何地方调用它,包括构造函数。您在这里所拥有的基本上是以下 Java 代码(当然,这里写的它是无效的,但它给出了基本思想):

public class QuickCheckPerson extends Properties {

    private final Person john;
    private volatile Arbitrary<Person> arbPerson;

    public QuickCheckPerson() {
        super("Person");  // call superclass constructor
        // property field belongs to superclass
        property.update("gen1", forAll(new Function1<Person, Boolean>() {
                /* closure implementation */ 
            },
            /* implicit parameter converting boolean to Prop */,
            arbPerson(),
            /* other implicits */
        ));
        this.john = Person.apply("john");
    }

    public Arbitrary<Person> arbPerson() {
        // Perform double-checked lock over a bit field (not presented here)
        // and create arbPerson if needed
        // Let's pretend that the following is double-checked lock:
        if (arbPerson == null) {
            arbPerson = Arbitrary.apply(value(john));
        }
        return arbPerson;
    }

}

JVM 中没有任何东西可以阻止您从构造函数调用方法,这就是这里发生的情况。arbPerson()在初始化字段之前调用方法john(默认情况下,所有引用字段都是空值),因此null提供给value()方法。因此你的NullPointerException.

请告诉我扩展Scala代码是否有任何错误(或直接编辑帖子),我会修复它们。

于 2013-11-15T10:35:42.537 回答