Kotlin `lazy`
Using lazy
in Kotlin
In Kotlin, the lazy
function is used to implement lazy initialization. This means that the value is computed only when it is accessed for the first time. This is particularly useful when the initialization of a variable is resource-intensive, and you want to delay its computation until it's actually needed.
Syntax
The basic syntax for lazy
is:
val property: Type by lazy {
// initialization code
}
Example
Let's consider a scenario where we have a class that computes a complex value. We'll use lazy
to initialize this value only when it's first accessed.
Code
package gt.sandbox
import gt.sandbox.util.output.Out
val out = Out.standard()
class ComplexCalculation {
// A lazily initialized property
val expensiveValue: Int by lazy {
out.println("Computing the value...")
performComplexCalculation()
}
private fun performComplexCalculation(): Int {
// Simulate a complex calculation
Thread.sleep(1000) // simulate a delay
return 42 // return some computed value
}
}
fun main() {
val calculation = ComplexCalculation()
// The expensiveValue is not computed until it's accessed for the first time
out.println("Before accessing expensiveValue")
out.println("The value is: ${calculation.expensiveValue}") // This triggers the calculation
out.println("After accessing expensiveValue")
out.println("Access it again does not trigger re-calculation: ${calculation.expensiveValue}") // This does not trigger the calculation
}
Command to reproduce:
gt.sandbox.checkout.commit 50c8258 \
&& cd "${GT_SANDBOX_REPO}" \
&& cmd.run.announce "./gradlew run"
Recorded output of command:
[2024-06-10T02:10:18.653542Z][ms-elapsed-since-start: 21][tname:main/tid:1] Before accessing expensiveValue
[2024-06-10T02:10:18.674603Z][ms-elapsed-since-start: 31][tname:main/tid:1] Computing the value...
[2024-06-10T02:10:19.684012Z][ms-elapsed-since-start: 1041][tname:main/tid:1] The value is: 42
[2024-06-10T02:10:19.684697Z][ms-elapsed-since-start: 1041][tname:main/tid:1] After accessing expensiveValue
[2024-06-10T02:10:19.685008Z][ms-elapsed-since-start: 1042][tname:main/tid:1] Access it again does not trigger re-calculation: 42
Explanation
- Declaration: The property
expensiveValue
is declared withval
and initialized usingby lazy
. - Lazy Initialization Block: The block inside
lazy
contains the initialization code, which in this case, callsperformComplexCalculation()
. - First Access: When
expensiveValue
is accessed for the first time, the initialization code runs, and the value is computed. Any subsequent accesses toexpensiveValue
will return the already computed value, without re-running the initialization block.
Benefits of lazy
- Performance Optimization: Avoids unnecessary computations until the value is actually needed.
- Thread Safety: The default mode of
lazy
isSYNCHRONIZED
, which ensures that the initialization block is executed only once in a thread-safe manner. Other modes (PUBLICATION
andNONE
) can be specified if different behavior is needed.
By using lazy
, you can ensure that resources are allocated only when necessary, making your application more efficient.