問題点
lazy関数でローカル変数を遅延初期化する場合、その変数を関数の引数として渡すと、
関数の呼び出し先でその変数を参照しなくても、関数を呼び出す時点で初期化が実行されてしまう。(LazyインスタンスのgetValueが呼ばれてしまう)
fun main() {
val value: String by lazy {
println("initialize value")
computeValue()
}
(1..3).forEach {
process(it, value)
}
}
private fun process(index: Int, value: String) {
println("index: $index")
if (index % 2 == 0) {
println("value: $value")
}
}
private fun computeValue(): String {
Thread.sleep(3000)
return "Hello"
}
結果
initialize value
index: 1
index: 2
value: Hello
index: 3
解決策
lazyなプロパティを保持するクラスを作成し、関数の引数として渡す。
class LazyValueProvider<T>(initializer: () -> T) {
val value: T by lazy {
initializer()
}
}
fun main() {
val provider = LazyValueProvider {
println("initialize value")
computeValue()
}
(1..3).forEach {
process(it, provider)
}
}
}
private fun process(index: Int, provider: LazyValueProvider<String>) {
println("index: $index")
if (index % 2 == 0) {
println("value: ${provider.value}")
}
}
private fun computeValue(): String {
Thread.sleep(3000)
return "Hello"
}
結果
index: 1
index: 2
initialize value
value: Hello
index: 3