lazy修飾變量就是為了延遲初始化
When a val is declared as lazy, its initialization is deferred until it is accessed for the first time.
- 場景一
在類的初始化的時候可能某個變量初始化比較耗時,那么可以使用lazy,等真正使用到這個變量的時候再初始化
scala> class Person{
| val properties = {
| //模擬長時間的某種操作
| println("init")
| Thread.sleep(2000)
| }
| }
defined class Person
scala> def main() {
| println("Start")
|
| val startTime = System.currentTimeMillis()
| val person = new Person
| val endTime = System.currentTimeMillis()
|
| println("End and take " + (endTime - startTime) + "ms")
|
| person.properties
| }
main: ()Unit
scala> main
Start
init
End and take 2002ms
可以看到new了一個對象,需要大約2000ms,如果改成lazy變量
scala> class Person{
| lazy val properties = {
| //模擬長時間的某種操作
| println("init")
| Thread.sleep(2000)
| }
| }
defined class Person
scala> main
Start
End and take 0ms
init
new操作幾乎瞬間完成,而且在真正使用變量的時候才初始化的
- 場景二
構造順序問題
trait Person{
val name: String
val nameLen = name.length
}
class Student extends Person{
override val name: String = "Tom"
}
如果這時候在main函數中new一個Student,會報空指針異常
這是因為父類的constructor先與子類執行,那么在執行val nameLen = name.length
的時候name
還沒有被賦值,所以才會導致空指針。
解決辦法就是在nameLen
前加lazy,延遲初始化
lazy val nameLen = name.length
- 缺點
每次使用前都會檢查是否已經初始化,會有額外的開銷,并沒有那么高效。