The Similar
val
, def
, lazy val
all exist to produce a value in Scala. Jolly good, right :)
The Different
To start with, values defined in val
are evaluated as soon as the object is initialised and the value will be stored throughout the lifetime of the object. Also the value defined by val
is immutable, it can’t be changed throughout the lifecycle either.
def
is used to define a method, just like the method in Java, it is evaluated every time it is called. As long as the type definition is satisfied, any value could be produced after its invocation.
Whereas lazy val
gives a little bit more flexibility, which is its value is only evaluated when first accessed, then the result is kept since, but can never be reassigned.
val
vs lazy val
When an object is created, all val
values are instantiated, which implies the resource is instantly allocated.
From the results in REPL, you can easily tell while Y
is processed straight away, it took 2 seconds before X
finishes instantiation. It is fine if this is indeed what you wanted.
But to speed up the application, it might worth considering only evaluate some values when they are needed, instead of in the beginning. Situation like this, it is ideal to use
lazy val
, which would save a lot of application initialisation time.
def
vs lazy val
So far, it may sound like lazy val
is just an immutable version of def
. Well, that’s not the whole picture.
There are two things you probably have noticed by running the two blocks of code:
- the print line in
lazy val
is only printed once, while the one indef
is printed a thousand times - value defined with
lazy val
executes more than twice as fast as the one defined withdef
The two observations are intriguingly linked because of the nature of lazy val
, which is a reference to start with, then turns into an immutable value and stays available throughout the process.
Therefore, it is worth adopting
lazy val
overdef
, if the value to access will never change and is likely to be accessed more than once.