ความแตกต่างระหว่างการใช้ Throwable และ Exception ในลอง catch


304

บางครั้งฉันเห็น

try {

} catch(Throwable e) {

}

และบางเวลา

try {

} catch(Exception e) {

}

อะไรคือความแตกต่าง?



คำตอบ:


247

โดยการจับมันรวมถึงสิ่งที่ประเภทรองThrowable Errorโดยทั่วไปคุณไม่ควรทำเช่นนั้นยกเว้นในระดับสูงสุด "ระดับทั้งหมด" ของเธรดที่คุณต้องการบันทึกหรือจัดการทุกอย่างที่ผิดพลาด มันจะเป็นเรื่องปกติมากขึ้นในแอ็พพลิเคชันชนิดของเฟรมเวิร์ก (ตัวอย่างเช่นแอ็พพลิเคชันเซิร์ฟเวอร์หรือเฟรมเวิร์กทดสอบ) ซึ่งสามารถรันโค้ดที่ไม่รู้จักและไม่ควรได้รับผลกระทบจากสิ่งใดก็ตามที่ผิดพลาดกับรหัสนั้น


30
อาจเป็นวิธีที่ดีที่สุดในการอธิบายลำดับชั้นเล็กน้อยที่นี่
Xonatron

11
บริบทสำหรับคำตอบนี้: Throwable มีทั้งข้อผิดพลาดและข้อยกเว้นเป็นคลาสย่อยดังนั้นการลอง / จับครั้งแรกจะรวมเป็นวินาที แต่มักจะกว้างเกินไป
Noel

2
นอกจากนี้ยังมีคลาสย่อยโดยตรงที่ผู้ใช้กำหนดของ Throwable และอินสแตนซ์ของ Throwable เอง ไม่มีอะไรหยุดคุณจากการเขียนthrow new Throwable();ดังนั้นจึงเป็นวิธีเดียวที่จะจับทุกอย่างได้อย่างแท้จริง
พลวง

3
แม้ว่าจะได้รับการยอมรับนี่ไม่ใช่การตอบคำถามเพราะคำตอบส่วนใหญ่อธิบายวิธีปฏิบัติที่ดีที่สุดในการจับทั้งข้อยกเว้นและการโยนได้และคำถามเกี่ยวกับความแตกต่าง (เช่นเมื่อใดควรใช้เมื่อใดเมื่อฉันต้องการ) "มันรวมถึงสิ่งต่าง ๆ ที่ข้อผิดพลาดของคลาสย่อย" มีความแตกต่างเพียงอย่างเดียวที่ระบุไว้และเป็นคำตอบที่ครอบคลุมจริงๆ: ข้อผิดพลาดคืออะไร ทำไมมันถึงมีความสำคัญ? ความแตกต่างอื่น ๆ หรือแนวทางปฏิบัติที่ดีที่สุด
Oded Niv

@OdedNiv "ข้อผิดพลาดคืออะไรทำไมมันถึงมีความสำคัญ?" คุณสามารถถามพวกเขาในคำถามอื่น
Kronen

182

คนแรกที่จับ subclasses ทั้งหมดThrowable(รวมถึงExceptionและError), คนที่สองจับ subclasses Exceptionทั้งหมดของ

Errorเป็นโปรแกรมที่ไม่สามารถกู้คืนได้ในทางใดทางหนึ่งและมักจะไม่ถูกดักจับยกเว้นเพื่อจุดประสงค์ในการบันทึก (ซึ่งส่งผ่านอีกครั้ง) Exceptionสามารถกู้คืนโดยทางโปรแกรม คลาสย่อยมันRuntimeExceptionระบุข้อผิดพลาดในการเขียนโปรแกรมและมักจะไม่ถูกจับเช่นกัน


37
ค่อนข้างน่าแปลกใจที่ 4 ปีหลังจากคำตอบนี้เครื่องมือ "การวิเคราะห์รหัส" ส่วนใหญ่จะยังคงรายงานการจับได้ว่าเป็นข้อผิดพลาดร้ายแรง การบันทึกเป็นเหตุผลที่ถูกต้องมากสำหรับการจับ Throwable หลายปีที่พัฒนาเซิร์ฟเวอร์บอกฉันว่า 1) การบันทึกจะเกิดขึ้นแม้จะได้รับErrorและ 2) เว้นแต่จะมีการบันทึกคุณอาจไม่เคยได้รับแจ้งว่ามี OOM เกิดขึ้นทำให้คุณสงสัยว่าทำไมเซิร์ฟเวอร์เริ่มทำงาน "ตลก"
Bruno Grieder

4
อะไรprogrammatically unrecoverableหมายความว่า? มันรุนแรงเหลือเกินที่เราไม่สามารถเรียกวิธีการใด ๆ ของ Java หลังจากที่จับมันอีกต่อไปแล้ว (การบันทึกเป็นต้น) โดยไม่มีโอกาสได้รับพฤติกรรมที่ไม่สามารถคาดเดาได้จาก JVM
Alexander Abakumov

Its subclass RuntimeException indicates a programming error: ไม่แน่ใจว่าฉันเห็นด้วยกับข้อความนี้หรือไม่ หากเป็นจริงก็หมายความว่าควรมีการตรวจสอบข้อยกเว้นที่คาดไว้ทั้งหมด ถ้าฉันคาดหวังว่าบางสิ่งอาจล้มเหลวและไม่สามารถกู้คืนได้โดยแอปพลิเคชันของฉัน แต่อย่างน้อยฉันก็ต้องการให้มีข้อยกเว้นที่มีความหมาย? การใช้ข้อยกเว้นที่ตรวจสอบในกรณีนั้นดูเหมือนว่าไร้ประโยชน์และสร้างรหัสสำเร็จรูป
Nom1fan

22

Thowableจับทุกอย่างแม้กระทั่ง ThreadDeath ซึ่งจะถูกโยนโดยค่าเริ่มต้นเพื่อหยุดเธรดจากThread.stop()วิธีที่เลิกใช้แล้ว ดังนั้นโดยการจับThrowableคุณสามารถมั่นใจได้ว่าคุณจะไม่ปล่อยให้บล็อกลองโดยไม่ต้องอย่างน้อยจะผ่านการตรวจจับบล็อกของคุณ แต่คุณควรเตรียมที่จะยังจัดการOutOfMemoryErrorและหรือInternalErrorStackOverflowError

การจับThrowableเป็นประโยชน์มากที่สุดสำหรับเซิร์ฟเวอร์ภายนอกลูปที่มอบหมายการร้องขอทุกประเภทให้กับรหัสภายนอก แต่ตัวเองอาจไม่เคยยุติเพื่อให้บริการมีชีวิตอยู่


21

Throwableเป็นชั้นสุดของเช่นเดียวกับException Errorในกรณีปกติเราควรจับคลาสย่อยเสมอExceptionเพื่อไม่ให้รากสาเหตุหายไป

กรณีพิเศษเฉพาะที่คุณเห็นเป็นไปได้ของสิ่งที่ผิดไปซึ่งไม่ได้อยู่ในการควบคุมของรหัส Java ของคุณคุณควรจับหรือErrorThrowable

ฉันจำได้ว่าจับได้ Throwable เพื่อตั้งค่าสถานะว่าไลบรารีดั้งเดิมไม่ได้โหลด


0

ฉันเคยเห็นคนใช้ Throwable เพื่อตรวจจับข้อผิดพลาดบางอย่างที่อาจเกิดขึ้นเนื่องจากความล้มเหลวของอินฟา / ไม่พร้อมใช้งาน

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.