lateinit และการเริ่มต้นแบบ Lazy
ใช้ lateinit กับพร็อพเพอร์ตีที่กำหนดค่าภายหลัง และใช้ by lazy สำหรับการคำนวณแบบเลื่อนเวลา
lateinit และการเริ่มต้นแบบ Lazy เป็นบทเรียน Kotlin Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Kotlin Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Kotlin Academy มีบทเรียนทั้งหมด 4 บทเรียน
เครื่องมือสองอย่างสำหรับการตั้งค่าภายหลัง
บางครั้งคุณไม่สามารถเริ่มต้นพร็อพเพอร์ตีในขณะสร้างออบเจ็กต์ได้ Kotlin จึงมีการเริ่มต้นภายหลังสำหรับตัวแปรที่กำหนดค่าทีหลัง และการเริ่มต้นแบบคำนวณเมื่อเข้าถึงครั้งแรกสำหรับค่าที่อ่านได้อย่างเดียว
พื้นฐานของการเริ่มต้นภายหลัง
lateinit var เลื่อนการเริ่มต้นออกไป ตัวแปรต้องเป็น var ที่ไม่เป็นค่าว่างและไม่ใช่ชนิดพื้นฐาน หากเข้าถึงก่อนกำหนดค่า จะเกิด UninitializedPropertyAccessException
class Service {
lateinit var name: String
fun init(value: String) { name = value }
}
fun main() {
val s = Service()
s.init("MyService")
println(s.name)
}เหตุผลที่ใช้การเริ่มต้นภายหลัง
ใช้ lateinit สำหรับการฉีดการพึ่งพา ชุดข้อมูลสำหรับการทดสอบ หรือวงจรชีวิตที่เฟรมเวิร์กจัดการ เช่น มุมมอง Android และ bean ของ Spring ซึ่งการเริ่มต้นเกิดขึ้นนอกตัวสร้าง
class Repository {
lateinit var db: String // assigned later by DI framework
fun query() = "querying $db"
}
fun main() {
val r = Repository()
r.db = "postgres://localhost"
println(r.query())
}การตรวจสอบการเริ่มต้น
คุณสามารถตรวจสอบว่าพร็อพเพอร์ตี lateinit ถูกกำหนดค่าแล้วหรือไม่ด้วย ::propName.isInitialized
class Foo {
lateinit var bar: String
fun status() = if (::bar.isInitialized) "set to $bar" else "unset"
}
fun main() {
val f = Foo()
println(f.status()) // unset
f.bar = "hi"
println(f.status())
}ข้อจำกัดของการเริ่มต้นภายหลัง
คุณไม่สามารถใช้ lateinit กับชนิดพื้นฐาน เช่น Int หรือ Boolean ชนิดที่รับค่าว่างได้ หรือ val ได้ คอมไพเลอร์จะบังคับใช้กฎเหล่านี้
// VALID:
lateinit var name: String
// INVALID:
// lateinit var count: Int // primitives not allowed
// lateinit val constant: String // val not allowed
// lateinit var maybe: String? // nullable not allowed
fun main() { name = "ok"; println(name) }พื้นฐานของการเริ่มต้นแบบขี้เกียจ
by lazy จะเลื่อนการเริ่มต้นของ val จนกว่าจะมีการเข้าถึงครั้งแรก แลมบ์ดาจะทำงานเพียงครั้งเดียวและผลลัพธ์จะถูกเก็บไว้ในแคช
val expensive: String by lazy {
println("Computing...")
"result"
}
fun main() {
println(expensive) // Computing... then result
println(expensive) // result (cached)
}เหตุผลที่ใช้การเริ่มต้นแบบขี้เกียจ
ใช้ by lazy เมื่อการเริ่มต้นใช้เวลาหรือทรัพยากรมากและอาจไม่จำเป็นต้องใช้ โดยเก็บค่าไว้ในแคชเพื่อใช้ภายหลัง หรือเมื่อการเริ่มต้นขึ้นอยู่กับพร็อพเพอร์ตีอื่นที่สร้างไว้แล้ว
class Config {
val parsed: Map<String, String> by lazy {
println("parsing config...")
mapOf("host" to "localhost", "port" to "8080")
}
}
fun main() {
val c = Config()
println("config object created — not parsed yet")
println(c.parsed["host"]) // now parses
println(c.parsed["port"]) // cached
}โหมดความปลอดภัยของเธรดสำหรับการเริ่มต้นแบบขี้เกียจ
โดยค่าเริ่มต้น by lazy จะใช้ LazyThreadSafetyMode.SYNCHRONIZED ใช้ PUBLICATION สำหรับการเริ่มต้นที่ทำงานพร้อมกันได้ และใช้ NONE เพื่อประสิทธิภาพในโปรแกรมที่มีเธรดเดียว
val safe: String by lazy { "thread-safe" }
val fast: String by lazy(LazyThreadSafetyMode.NONE) { "fast, single-thread" }
fun main() {
println(safe)
println(fast)
}การเริ่มต้นภายหลังเทียบกับการเริ่มต้นแบบขี้เกียจ
การเริ่มต้นภายหลัง: var ซึ่งกำหนดค่าจากภายนอก การเริ่มต้นแบบขี้เกียจ: val ซึ่งพร็อพเพอร์ตีคำนวณค่าเองเมื่อถูกเข้าถึงครั้งแรก
class Demo {
lateinit var injected: String // assigned by caller
val computed: String by lazy { "computed once" }
}
fun main() {
val d = Demo()
d.injected = "from outside"
println(d.injected)
println(d.computed)
}การอ่านพร็อพเพอร์ตีอื่นด้วยการเริ่มต้นแบบขี้เกียจ
พร็อพเพอร์ตีแบบขี้เกียจสามารถอ่านพร็อพเพอร์ตีอื่นที่เริ่มต้นไว้ก่อนแล้วและนำค่ามาประกอบกันได้
class User(val first: String, val last: String) {
val fullName: String by lazy { "$first $last" }
}
fun main() {
val u = User("Ada", "Lovelace")
println(u.fullName)
}รูปแบบการใช้งานจริง
ใช้การเริ่มต้นภายหลังสำหรับการฉีดการพึ่งพา และใช้การเริ่มต้นแบบขี้เกียจสำหรับสถานะที่ได้จากการคำนวณภายในคลาสเดียวกัน
class App {
lateinit var config: Map<String, String>
val host: String by lazy { config["host"] ?: "localhost" }
}
fun main() {
val app = App()
app.config = mapOf("host" to "api.example.com")
println(app.host) // api.example.com
}ตรวจสอบอย่างรวดเร็ว
คำสำคัญใดเลื่อนการเริ่มต้นของพร็อพเพอร์ตี val จนกว่าจะมีการเข้าถึงครั้งแรก
สรุปทบทวน
ใช้ ตัวแปรที่เริ่มต้นภายหลัง สำหรับพร็อพเพอร์ตีที่แก้ไขได้และไม่เป็นค่าว่าง ซึ่งเฟรมเวิร์กหรือการฉีดการพึ่งพาจะกำหนดค่าภายหลัง ใช้ ค่าที่อ่านได้อย่างเดียวแบบเริ่มต้นขี้เกียจ สำหรับค่าที่ควรคำนวณเพียงครั้งเดียวเมื่อเข้าถึงครั้งแรก ตรวจสอบสถานะด้วย ::prop.isInitialized
คำถามที่พบบ่อย
บทเรียน “lateinit และการเริ่มต้นแบบ Lazy” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “lateinit และการเริ่มต้นแบบ Lazy” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Kotlin Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Kotlin Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “lateinit และการเริ่มต้นแบบ Lazy”
ใช้ lateinit กับพร็อพเพอร์ตีที่กำหนดค่าภายหลัง และใช้ by lazy สำหรับการคำนวณแบบเลื่อนเวลา คุณปฏิบัติ Kotlin Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Kotlin Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน Kotlin Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน
บทเรียน “lateinit และการเริ่มต้นแบบ Lazy” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน Kotlin Academy นี้ได้ไหม
ได้ บทเรียน Kotlin Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- คอนสตรักเตอร์หลักและพารามิเตอร์พร็อพเพอร์ตี
- บล็อก init และลำดับการเริ่มต้น
- Getter และ Setter แบบกำหนดเองด้วย field
- lateinit และการเริ่มต้นแบบ Lazy