If a client val
is lazy
, but it's not called, and .close()
is executed, will it throw an error?
Example:
private lazy val cloudWatchClient = CloudWatchClient.builder.region(region).build
cloudWatchClient
isn't called.
Later, we'll attempt to close it
try {
cloudWatchClient.close()
}
Does this mean the cloudWatchClient
client will open and then closed every time if it's not called at line cloudWatchClient.close()
?
CodePudding user response:
No, it will not throw an error (unless you implemented CloudWatchClient
to do that on purpose when being initialized). When you prefix a val
definition with a lazy
modifier, the initializing expression on the right-hand side will only be evaluated the first time the val
is used.
Here's a nice example that shows the difference. First a normal object:
scala> object SomeObj {
val x = {
println("initializing x")
"done"
}
}
defined object SomeObj
scala> SomeObj
initializing x
val res0: SomeObj.type = SomeObj$@7c3c3d67
scala> SomeObj.x
val res1: String = done
Now an object containing a lazy val
:
scala> object SomeLazyObj {
lazy val x = {
println("initializing lazy x")
"done"
}
}
defined object SomeLazyObj
scala> SomeLazyObj
val res2: SomeLazyObj.type = SomeLazyObj$@3e4636c3
scala> SomeLazyObj.x
initializing lazy x
val res3: String = done
You can probably now figure that intuitively what lazy
does in your example is to avoid initializing cloudWatchClient
on the spot. In fact, its initialization happens exactly before close()
is called, since operands are evaluated left-to-right, and the method close()
needs cloudWatchClient
initialized before it can itself be called.
It is worth noting that unlike a def
, a lazy val
is never evaluated more than once. After the first evaluation of the lazy val
, the result is stored, to be reused when the same val
is used subsequently.
However, there is one trick to it: if during the first evaluation of your lazy val
you get an Exception
, the next time you will try to access the lazy val
, it will try to re-evaluate itself.