Разница между ними заключается в том, что val
выполняется, когда он определен, тогда как lazy val
выполняется, когда к нему обращаются в первый раз.
scala> val x = { println("x"); 15 }
x
x: Int = 15
scala> lazy val y = { println("y"); 13 }
y: Int = <lazy>
scala> x
res2: Int = 15
scala> y
y
res3: Int = 13
scala> y
res4: Int = 13
В отличие от метода (определенного с помощью def
) lazy val
выполняется один раз, а затем никогда больше. Это может быть полезно, когда операция занимает много времени и когда она не уверена, будет ли она использоваться позже.
scala> class X { val x = { Thread.sleep(2000); 15 } }
defined class X
scala> class Y { lazy val y = { Thread.sleep(2000); 13 } }
defined class Y
scala> new X
res5: X = X@262505b7 // we have to wait two seconds to the result
scala> new Y
res6: Y = Y@1555bd22 // this appears immediately
Здесь, когда значения x
и y
никогда не используются, только x
излишне тратит ресурсы. Если мы предположим, что y
не имеет побочных эффектов и что мы не знаем, как часто к нему обращаются (никогда, один раз, тысячи раз), бесполезно объявлять его как def
, так как мы не хотим его выполнять несколько раз.
Если вы хотите узнать, как реализовано lazy vals
, посмотрите этот вопрос .