Scala的val、def、lazy val有什么不同

Scala

Scala的val、def、lazy val有什么不同

> scala
Welcome to Scala 2.12.4 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_144).
Type in expressions for evaluation. Or try :help.
> scala@2.11
Welcome to Scala 2.11.11 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_144).
Type in expressions for evaluation. Or try :help.

def method

  • In scala 2.11.11
scala> :paste
// Entering paste mode (ctrl-D to finish)

def even: Int => Boolean = _ % 2 == 0
even eq even

// Exiting paste mode, now interpreting.

even: Int => Boolean
res0: Boolean = false

scala> System.identityHashCode(even)
res17: Int = 969115094

scala> System.identityHashCode(even)
res18: Int = 2089636626

Method def even evaluates on call and creates new function every time (new instance of Function1) in scala 2.11.11

  • In scala 2.12.4
scala> :paste
// Entering paste mode (ctrl-D to finish)

def even: Int => Boolean = _ % 2 == 0
even eq even

// Exiting paste mode, now interpreting.

even: Int => Boolean
res0: Boolean = true

scala> System.identityHashCode(even)
res19: Int = 1803942588

scala> System.identityHashCode(even)
res20: Int = 1803942588

val method

  • scala 2.11.11
scala> :paste
// Entering paste mode (ctrl-D to finish)

val even: Int => Boolean = _ % 2 == 0
even eq even

// Exiting paste mode, now interpreting.

even: Int => Boolean = <function1>
res1: Boolean = true
  • scala 2.12.4 same

Return the same value when using val in both 2.11/2.12

  • scala 2.11.11
scala> :paste
// Entering paste mode (ctrl-D to finish)

val test: () => Int = {
  val r = util.Random.nextInt
  () => r
}

// Exiting paste mode, now interpreting.

test: () => Int = <function0>

scala> test()
res2: Int = -1716734099

scala> test()
res3: Int = -1716734099
  • 2.12.4 same

Return new function when using def in both 2.11/2.12

  • scala 2.11.11
scala> :paste
// Entering paste mode (ctrl-D to finish)

def test: () => Int = {
  val r = util.Random.nextInt
  () => r
}

// Exiting paste mode, now interpreting.

test: () => Int

scala> test()
res4: Int = -2141044486

scala> test()
res5: Int = 793997349
  • 2.12.4 same

val evaluates when defined

  • scala 2.11.11
scala> val even: Int => Boolean = ???
scala.NotImplementedError: an implementation is missing
  at scala.Predef$.$qmark$qmark$qmark(Predef.scala:230)
  ... 32 elided
  • 2.12.4 same

def evaluates when called

  • scala 2.11.11
scala> def even: Int => Boolean = ???
even: Int => Boolean

scala> even
scala.NotImplementedError: an implementation is missing
  at scala.Predef$.$qmark$qmark$qmark(Predef.scala:230)
  at .even(<console>:11)
  ... 32 elided

scala>
  • 2.12.4 same

lazy val evaluates only when first time been called, but return the result initialized in the first time:

  • scala 2.11.11
scala> lazy val even: Int => Boolean = ???
even: Int => Boolean = <lazy>
scala> :paste
// Entering paste mode (ctrl-D to finish)

lazy val test: () => Int = {
  val r = util.Random.nextInt
  () => r
}

// Exiting paste mode, now interpreting.

test: () => Int = <lazy>

scala> test
res8: () => Int = <function0>

scala> test()
res9: Int = 822922251

scala> test()
res10: Int = 822922251
  • 2.12.4 same

结论:

  • val定义完后就执行。

  • def调用时才执行,scala2.12为def做了一些优化。如果从来没调用过def定义的方法里面的代码不会执行。

  • lazy val第一次调用时执行,以后调用就返回第一次调用初始化后的值。如果从来没调用过就永远也不会执行初始化块。但是每次调用lazy val定义的function时都会检查这个属性是不是已经被初始化过了…

  • 如果需要定义一个method

def even(i: Int): Boolean = i % 2 == 0
  • 如果需要定义一个function,为了避免每次传递这个function都会创建一个新的对象(scala 2.11):
val even: Int => Boolean = _ % 2 == 0
  • 而对于scala2.12 不需要特别考虑上面两个规则,因为scala2.12不会为def定义的方法每次调用时都生成新的function,但是为了保持语义上的同一建议还是参考上面两条建议。

Original link:https://izhangzhihao.github.io//2017/11/15/Scala的val-def-lazy-val有什么不同/

Search

    Table of Contents