Kotlin Academy · บทเรียน

การโยน Exception ซ้ำและการเชื่อมโยง Exception

เลือกโยน exception ซ้ำตามเงื่อนไข และห่อข้อผิดพลาดระดับล่างพร้อมเชื่อมโยงสาเหตุ

บทเรียน 4 จาก 413 ขั้นตอน

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

การโยนซ้ำและการห่อหุ้ม

บางครั้งคุณดักจับข้อยกเว้นเพียงเพื่อบันทึก ห่อหุ้ม หรือแปลงข้อยกเว้นนั้น ก่อนปล่อยให้ข้อยกเว้นที่เฉพาะเจาะจงกว่าถูกส่งต่อ Kotlin ทำให้รูปแบบนี้เป็นธรรมชาติ

การโยนซ้ำโดยตรง

เมื่อต้องการโยนซ้ำ เพียงใช้ throw e อีกครั้ง การส่งต่อจะดำเนินต่อไปยังตัวจัดการถัดไป

fun main() {
    try {
        try { "x".toInt() }
        catch (e: NumberFormatException) {
            println("logging: ${e.message}")
            throw e // re-throw original
        }
    } catch (e: NumberFormatException) {
        println("outer caught: ${e.message}")
    }
}

การห่อหุ้มด้วยข้อยกเว้นแบบกำหนดเอง

ส่งข้อยกเว้นเดิมเป็น cause เมื่อสร้างข้อยกเว้นใหม่ เพื่อรักษาสายโซ่ของข้อยกเว้น

class ParseException(msg: String, cause: Throwable) : RuntimeException(msg, cause)
fun main() {
    try {
        try { "xyz".toInt() }
        catch (e: NumberFormatException) {
            throw ParseException("could not parse user input", e)
        }
    } catch (e: ParseException) {
        println("got: ${e.message}")
        println("cause: ${e.cause?.message}")
    }
}

การตรวจสอบสายโซ่ของสาเหตุ

คุณสมบัติ cause เชื่อมโยงไปยังข้อยกเว้นก่อนหน้า ให้ไล่ตามสายโซ่นี้เพื่อพิมพ์สาเหตุรากทั้งหมด

fun main() {
    val e = RuntimeException("top",
        RuntimeException("middle",
            RuntimeException("root")))
    var current: Throwable? = e
    while (current != null) {
        println(current.message)
        current = current.cause
    }
}

การโยนซ้ำแบบเลือกเฉพาะ

ดักจับชนิดกว้างก่อน แล้วโยนซ้ำหากไม่ตรงกับกรณีที่คาดหมาย

fun parseRequired(s: String): Int {
    try {
        return s.toInt()
    } catch (e: NumberFormatException) {
        if (s.isBlank()) return 0
        throw e // unexpected — let it propagate
    }
}
fun main() {
    println(parseRequired("42"))
    println(parseRequired(""))
    // parseRequired("abc") // throws
}

การเพิ่มบริบท

ห่อหุ้มด้วยข้อยกเว้นของโดเมนเพื่อเพิ่มบริบทที่ข้อยกเว้นเดิมไม่มี เช่น ข้อมูลเข้า รหัสคำขอ และอื่น ๆ

class UploadError(msg: String, cause: Throwable) : RuntimeException(msg, cause)
fun upload(file: String) {
    try { throw RuntimeException("disk full") }
    catch (e: Throwable) { throw UploadError("uploading $file failed", e) }
}
fun main() {
    try { upload("photo.jpg") }
    catch (e: UploadError) { println("${e.message} <- ${e.cause?.message}") }
}

อย่าทำสแต็กเทรซหาย

เมื่อห่อหุ้ม ให้ส่งข้อยกเว้นเดิมเป็น cause เสมอ อย่าสร้างข้อยกเว้นใหม่ที่มีเพียงข้อความเดียวกันแต่ไม่มีสาเหตุเดิม สแต็กเทรซคือสิ่งสำคัญในการแก้ไขข้อผิดพลาด

class Wrapped(m: String, cause: Throwable) : RuntimeException(m, cause)
fun main() {
    try {
        try { error("inner") }
        catch (e: Throwable) { throw Wrapped("outer", e) }
    } catch (e: Wrapped) {
        println("message: ${e.message}")
        println("cause: ${e.cause?.message}")
    }
}

โยนซ้ำโดยไม่ห่อหุ้ม

หากต้องการเพียงบันทึก ก็ใช้ throw e หลังการเรียกบันทึกได้เลย โดยไม่ต้องห่อหุ้ม

fun risky() {
    try { throw IllegalStateException("oops") }
    catch (e: IllegalStateException) {
        println("Logging before rethrow: ${e.message}")
        throw e
    }
}
fun main() {
    try { risky() }
    catch (e: IllegalStateException) { println("outer: ${e.message}") }
}

finally สำหรับการเก็บกวาดระหว่างโยนซ้ำ

ใช้ finally เพื่อเก็บกวาดทรัพยากรแม้จะมีการโยนข้อยกเว้นซ้ำ

fun process() {
    try {
        throw RuntimeException("failure")
    } finally {
        println("cleanup ran")
    }
}
fun main() {
    try { process() }
    catch (e: RuntimeException) { println("caught: ${e.message}") }
}

ข้อยกเว้นที่ถูกระงับ

หาก finally เองโยนข้อยกเว้น ข้อยกเว้นเดิมจะถูกระงับเป็นค่าเริ่มต้น ใช้ addSuppressed เพื่อรักษาข้อยกเว้นทั้งสองรายการไว้

fun main() {
    val primary = RuntimeException("primary")
    val secondary = RuntimeException("from cleanup")
    primary.addSuppressed(secondary)
    println(primary.suppressed.joinToString { it.message ?: "?" })
}

รูปแบบที่ไม่ควรใช้: กลืนข้อยกเว้นแล้วโยนข้อยกเว้นอื่น

การดักจับข้อยกเว้นหนึ่งรายการแล้วโยนข้อยกเว้นใหม่ที่ไม่เกี่ยวข้องกัน (โดยไม่ระบุสาเหตุ) จะทำลายข้อมูลสำหรับการดีบัก โปรดส่งต่อ cause เสมอ

// BAD
// catch (e: IOException) { throw RuntimeException("error") }
// GOOD
// catch (e: IOException) { throw RuntimeException("error reading config", e) }
fun main() { println("Pass cause when re-throwing!") }

ตรวจสอบอย่างรวดเร็ว

เมื่อห่อข้อยกเว้นไว้ในข้อยกเว้นใหม่ ควรทำอย่างไรเพื่อเก็บรักษาร่องรอยสแตกเดิมไว้

ทบทวน

หากต้องการโยนซ้ำ ให้ใช้ throw e หากต้องการห่อ ให้โยนข้อยกเว้นใหม่โดยกำหนด cause = e โปรดเก็บรักษาลำดับสาเหตุไว้เสมอ อย่าสร้างตัวห่อหุ้มที่ไม่มีสาเหตุ ใช้ finally สำหรับการทำความสะอาด และใช้ addSuppressed เมื่อการทำความสะอาดล้มเหลวเอง

เริ่มต้นได้ฟรี

เรียนรู้ Kotlin ด้วย AI tutor — ฟรี

เขียนและเรียกใช้โค้ดจริงในเบราว์เซอร์ของคุณ รับความช่วยเหลือทันทีจาก AI tutor 24/7 และเรียนรู้ต่อจากที่คุณหยุดบนเว็บหรือในแอป

คอร์ส
51
บทเรียน
203

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

บทเรียน “การโยน Exception ซ้ำและการเชื่อมโยง Exception” ฟรีหรือไม่

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

คุณจะเรียนรู้อะไรในบทเรียน “การโยน Exception ซ้ำและการเชื่อมโยง Exception”

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

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

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

บทเรียน “การโยน Exception ซ้ำและการเชื่อมโยง Exception” ใช้เวลานานแค่ไหน

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

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

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

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

  1. try/catch/finally ในฐานะนิพจน์
  2. การสร้างคลาส Exception แบบกำหนดเอง
  3. runCatching และ Result
  4. การโยน Exception ซ้ำและการเชื่อมโยง Exception
← กลับไปที่ Kotlin Academy