0Pricing
Kotlin Academy · บทเรียน

by lazy: เจาะลึกการเริ่มต้นแบบเลื่อนเวลา

สำรวจโหมดการเริ่มต้นแบบ lazy ได้แก่ SYNCHRONIZED, PUBLICATION และ NONE

by lazy: เจาะลึกการเริ่มต้นแบบเลื่อนเวลา เป็นบทเรียน Kotlin Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Kotlin Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Kotlin Academy มีบทเรียนทั้งหมด 4 บทเรียน

by lazy คืออะไร

by lazy จะเลื่อนการเริ่มต้นค่า val จนกว่าจะมีการเข้าถึงครั้งแรก แลมบ์ดาจะทำงานเพียงครั้งเดียวและแคชผลลัพธ์ไว้

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 รับแลมบ์ดาที่ส่งคืนชนิดค่าซึ่งอนุมานจากการประกาศพร็อพเพอร์ตี

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

ใช้ by lazy กับ val ที่มีการเริ่มต้นค่าซับซ้อน ใช้ lateinit กับ var ที่กำหนดค่าจากภายนอก เช่น ในการทดสอบหรือการฉีดการพึ่งพา

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

ตรวจสอบว่าพร็อพเพอร์ตีแบบ lazy เริ่มต้นค่าแล้วหรือไม่ด้วย .isInitialized() แต่ทำได้ผ่านการอ้างอิงตัวแทนเท่านั้น

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 อื่น ๆ ได้ ทำให้สร้างสายการเริ่มต้นค่าแบบ 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)
}

การใช้งานจริง: บริการ Singleton

ใช้ by lazy ในการประกาศ object เพื่อเริ่มต้น Singleton ที่ใช้ทรัพยากรมากเมื่อจำเป็น

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
}

การคอมไพล์ Regex แบบ Lazy

การคอมไพล์ regex ใช้ทรัพยากรมาก ใช้ 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 จะเรียกใช้แลมบ์ดาครั้งเดียวเมื่อมีการเข้าถึงครั้งแรก และแคชผลลัพธ์ไว้ เลือก SYNCHRONIZED (ค่าเริ่มต้น) เพื่อความปลอดภัยระหว่างเธรด เลือก PUBLICATION สำหรับการเริ่มต้นแบบทำซ้ำได้อย่างปลอดภัยพร้อมกันหลายเธรด และเลือก NONE เพื่อประสิทธิภาพในสภาพแวดล้อมที่มีเธรดเดียว

คำถามที่พบบ่อย

บทเรียน “by lazy: เจาะลึกการเริ่มต้นแบบเลื่อนเวลา” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “by lazy: เจาะลึกการเริ่มต้นแบบเลื่อนเวลา” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Kotlin Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Kotlin Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “by lazy: เจาะลึกการเริ่มต้นแบบเลื่อนเวลา”

สำรวจโหมดการเริ่มต้นแบบ lazy ได้แก่ SYNCHRONIZED, PUBLICATION และ NONE คุณปฏิบัติ Kotlin Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Kotlin Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน Kotlin Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน

บทเรียน “by lazy: เจาะลึกการเริ่มต้นแบบเลื่อนเวลา” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน Kotlin Academy นี้ได้ไหม

ได้ บทเรียน Kotlin Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. by lazy: เจาะลึกการเริ่มต้นแบบเลื่อนเวลา
  2. ตัวแทน observable และ vetoable
  3. การเขียนตัวแทน ReadWriteProperty แบบกำหนดเอง
  4. ตัวแทนสำหรับ Preferences พร็อพเพอร์ตีที่ใช้ Map และการบันทึก
← กลับไปที่ Kotlin Academy