by lazy:深入了解延迟初始化
探索延迟初始化模式:SYNCHRONIZED、PUBLICATION 和 NONE。
by lazy:深入了解延迟初始化 是 CoddyKit 上的免费 Kotlin Academy 课时。 这是第 1 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Kotlin Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Kotlin Academy 课程共包含 4 节课。
什么是 by lazy?
by lazy 会将 val 的初始化延迟到第一次访问时执行。Lambda 表达式只运行一次,并缓存结果。
val greeting: String by lazy {
println("Computing...")
"Hello, Kotlin!"
}
fun main() {
println(greeting) // prints Computing... then Hello, Kotlin!
println(greeting) // prints Hello, Kotlin! (cached)
}Lazy 语法
by lazy 委托接收一个 Lambda 表达式,其返回值类型会根据属性声明自动推断。
val pi: Double by lazy { Math.PI }
val appName: String by lazy { "MyApp v1.0" }
fun main() {
println(pi) // 3.141592653589793
println(appName) // MyApp v1.0
}SYNCHRONIZED 模式(默认)
默认情况下,lazy 使用 LazyThreadSafetyMode.SYNCHRONIZED:只有一个线程会初始化该值。
val heavyResource: String by lazy(LazyThreadSafetyMode.SYNCHRONIZED) {
Thread.sleep(100) // simulate work
"Resource ready"
}
fun main() { println(heavyResource) }PUBLICATION 模式
PUBLICATION 允许多个线程并发初始化;最终采用第一个结果。适合初始化成本低且没有副作用的场景。
val config: Map<String, String> by lazy(LazyThreadSafetyMode.PUBLICATION) {
mapOf("host" to "localhost", "port" to "8080")
}
fun main() { println(config["host"]) }NONE 模式
NONE 不产生同步开销。只有在单线程环境且性能很重要时才应使用它。
val singleThreadValue: Int by lazy(LazyThreadSafetyMode.NONE) {
42
}
fun main() { println(singleThreadValue) }类中的 Lazy
类中的 by lazy 会在第一次访问属性时初始化,适合执行与实例状态相关的高成本计算。
class DatabaseConnection(val url: String) {
val pool: String by lazy {
println("Connecting to $url")
"Pool@$url"
}
}
fun main() {
val db = DatabaseConnection("localhost:5432")
println(db.pool)
}Lazy 与 lateinit
对于初始化过程复杂的 val,请使用 by lazy。对于由外部赋值的 var(例如在测试或依赖注入中),请使用 lateinit。
class MyService {
val computed: List<Int> by lazy { (1..100).toList() }
lateinit var injected: String
}
fun main() {
val s = MyService()
s.injected = "injected value"
println(s.computed.size)
println(s.injected)
}isInitialized 检查
可以通过 .isInitialized() 检查 Lazy 属性是否已初始化,但只能通过委托引用进行检查。
val myLazy: String by lazy { "initialized" }
fun main() {
val ref = ::myLazy
// No direct isInitialized on val lazy, but we can check via delegate
println(myLazy)
}带依赖的 Lazy
Lazy 属性可以引用其他 Lazy 属性,从而构建延迟初始化链。
val baseUrl: String by lazy { "https://api.example.com" }
val usersUrl: String by lazy { "$baseUrl/users" }
val postsUrl: String by lazy { "$baseUrl/posts" }
fun main() {
println(usersUrl)
println(postsUrl)
}实践:单例服务
在 object 声明中使用 by lazy,可以按需初始化重量级单例。
object Analytics {
val client: String by lazy {
println("Initializing analytics client")
"AnalyticsClient@ready"
}
}
fun main() {
println("App started")
println(Analytics.client) // initialized on first use
println(Analytics.client) // cached
}延迟编译正则表达式
编译正则表达式的成本很高。使用 by lazy 可以只编译一次并重复使用,避免反复产生开销。
val emailRegex: Regex by lazy {
Regex("^[A-Za-z0-9+_.-]+@(.+)$")
}
fun isValidEmail(email: String) = emailRegex.matches(email)
fun main() {
println(isValidEmail("user@example.com")) // true
println(isValidEmail("bad-email")) // false
}快速检查
在单线程环境中,为了获得最高性能,应该使用哪种 Lazy 模式?
回顾
by lazy 会在第一次访问时运行一次 Lambda 表达式,并缓存结果。线程安全请选择默认的 SYNCHRONIZED,并发且幂等的初始化请选择 PUBLICATION,单线程性能场景请选择 NONE。
常见问题解答
「by lazy:深入了解延迟初始化」课时是免费的吗?
是的 — 「by lazy:深入了解延迟初始化」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Kotlin Academy 课程的其余内容,请升级到 CoddyKit PRO。 Kotlin Academy 课程共包含 4 节课。
「by lazy:深入了解延迟初始化」这节课中我会学到什么?
探索延迟初始化模式:SYNCHRONIZED、PUBLICATION 和 NONE。 你通过在浏览器中直接运行的动手代码来练习 Kotlin Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Kotlin Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Kotlin Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 1 节课,共 4 节。
「by lazy:深入了解延迟初始化」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Kotlin Academy 课中编写并运行代码吗?
能。每节 Kotlin Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。