ข้อยกเว้น Java เป็นกลไกความสอดคล้องของ Java เพื่อระบุและตอบสนองต่อข้อผิดพลาด
กลไกการยกเว้น Java สามารถแยกรหัสการจัดการข้อยกเว้นในโปรแกรมจากรหัสธุรกิจปกติตรวจสอบให้แน่ใจว่ารหัสโปรแกรมนั้นสง่างามมากขึ้นและปรับปรุงความทนทานของโปรแกรม เมื่อใช้ข้อยกเว้นอย่างมีประสิทธิภาพข้อยกเว้นสามารถตอบคำถามทั้งสามข้อนี้ได้อย่างชัดเจน: ประเภทข้อยกเว้นคำตอบ "อะไร" และข้อยกเว้นสแต็กร่องรอยคำตอบ "ที่" และข้อมูลข้อยกเว้นคำตอบ "ทำไม" ถูกโยนทิ้ง
คำหลักหลายคำที่ใช้ในกลไกการยกเว้น Java: ลองจับในที่สุดโยนโยน
| คำสำคัญ | อธิบาย |
|---|---|
| พยายาม | ใช้สำหรับการฟัง ใส่รหัสที่จะฟัง (รหัสที่อาจส่งข้อยกเว้น) ในบล็อกคำสั่งลอง เมื่อข้อยกเว้นเกิดขึ้นในบล็อกคำสั่งลองข้อยกเว้นจะถูกโยนลงไป |
| จับ | ใช้เพื่อจับข้อยกเว้น Catch ใช้เพื่อจับข้อยกเว้นที่เกิดขึ้นในบล็อกคำสั่งลอง |
| ในที่สุด | ในที่สุดบล็อกคำสั่งจะถูกดำเนินการเสมอ ส่วนใหญ่จะใช้ในการรีไซเคิลทรัพยากรวัสดุ (เช่นการเชื่อมต่อฐานข้อมูลการเชื่อมต่อเครือข่ายและไฟล์ดิสก์) ที่เปิดในบล็อกลอง หลังจากการดำเนินการของบล็อกในที่สุดจะส่งคืนหรือโยนคำสั่งในการลองหรือจับบล็อก หากมีการใช้งบสุดท้ายเช่นการส่งคืนหรือการโยนพวกเขาจะไม่ข้ามกลับไปดำเนินการและจะหยุดโดยตรง |
| โยน | ใช้เพื่อโยนข้อยกเว้น |
| โยน | ใช้ในลายเซ็นวิธีการเพื่อประกาศข้อยกเว้นที่อาจถูกโยนลงโดยวิธีการ |
ระดับสาธารณะ DEMO1 {โมฆะคงที่สาธารณะหลัก (สตริง [] args) {ลอง {int i = 10/0; System.out.println ("i ="+i); } catch (arithmeticexception e) {system.out.println ("จับข้อยกเว้น"); System.out.println ("e.getMessage ():" + e.getMessage ()); System.out.println ("E.ToString ():" + E.ToString ()); System.out.println ("E.PrintStackTrace ():"); E.PrintStackTrace (); - ผลการทำงาน:
จับข้อยกเว้น. getMessage (): / โดย zeroe.toString (): java.lang.arithmeticexception: / โดย zeroe.printstacktrace (): java.lang.arithmeticexception: / โดยศูนย์ที่ demo1.main (demo1.java:6)
คำอธิบายผลลัพธ์: มีการดำเนินการที่มีตัวหารของ 0 ในบล็อกคำสั่งลองและการดำเนินการจะโยน java.lang.arithmeticexception ยกเว้น โดยการจับข้อยกเว้นจะถูกจับ
การสังเกตผลลัพธ์ที่เราพบว่า system.out.println ("i ="+i) ไม่ได้ดำเนินการ ซึ่งหมายความว่าหลังจากข้อยกเว้นเกิดขึ้นในบล็อกคำสั่งลองเนื้อหาที่เหลือในบล็อกคำสั่งลองจะไม่ถูกดำเนินการอีกต่อไป
ตัวอย่างที่ 2: เข้าใจการใช้งานพื้นฐานของในที่สุด
ขึ้นอยู่กับ "ตัวอย่างหนึ่ง" เราเพิ่มคำสั่งในที่สุด
คลาสสาธารณะ Demo2 {โมฆะคงที่สาธารณะหลัก (สตริง [] args) {ลอง {int i = 10/0; System.out.println ("i ="+i); } catch (arithmeticexception e) {system.out.println ("จับข้อยกเว้น"); System.out.println ("e.getMessage ():" + e.getMessage ()); System.out.println ("E.ToString ():" + E.ToString ()); System.out.println ("E.PrintStackTrace ():"); E.PrintStackTrace (); } ในที่สุด {system.out.println ("เรียกใช้ในที่สุด"); - ผลการทำงาน:
ข้อยกเว้นที่จับได้ GetMessage (): / โดย Zeroe.toString (): java.lang.arithmeticexception: / โดย Zeroe.printstacktrace (): java.lang.arithmeticexception: / โดยศูนย์ที่ demo2.main (demo2.java:6)
ผลลัพธ์: ในที่สุดบล็อกคำสั่งถูกดำเนินการ
ตัวอย่างที่ 3: เข้าใจการใช้งานขั้นพื้นฐานของการโยนและโยน
การโยนใช้เพื่อประกาศข้อยกเว้นที่ถูกโยนทิ้งในขณะที่การโยนถูกใช้เพื่อโยนข้อยกเว้น
Class MyException ขยายข้อยกเว้น {Public MyException () {} myException สาธารณะ (String msg) {super (msg); }} คลาสสาธารณะ demo3 {โมฆะคงที่สาธารณะหลัก (สตริง [] args) {ลอง {test (); } catch (myexception e) {system.out.println ("จับข้อยกเว้นของฉัน"); E.PrintStackTrace (); }} การทดสอบโมฆะแบบคงที่สาธารณะ () พ่น myexception {ลอง {int i = 10/0; System.out.println ("i ="+i); } catch (arithmeticexception e) {โยน myexception ใหม่ ("นี่คือ myexception"); - ผลการทำงาน:
จับข้อยกเว้นของฉัน: นี่คือ myexception ที่ demo3.test (demo3.java:24) ที่ demo3.main (demo3.java:13)
ผลลัพธ์: MyException เป็นคลาสย่อยที่สืบทอดมาจากข้อยกเว้น arithmeticexception exception (ตัวหารคือ 0) ถูกสร้างขึ้นในบล็อกคำสั่งลองของการทดสอบ () และข้อยกเว้นจะถูกจับในการจับ; จากนั้นข้อยกเว้น myexception จะถูกโยน วิธีการหลัก () จับภาพ myexception ที่โยนในการทดสอบ ()
กรอบข้อยกเว้น Java
แผนภาพสถาปัตยกรรม Java Exception:
1.
Throwable เป็น superclass ของข้อผิดพลาดหรือข้อยกเว้นทั้งหมดในภาษา Java
Throwable มีสองคลาสย่อย: ข้อผิดพลาดและข้อยกเว้น พวกเขามักจะใช้เพื่อบ่งบอกถึงความผิดปกติที่เกิดขึ้น
THINDABLE ประกอบด้วยสแน็ปช็อตของเธรดที่ดำเนินการสแต็กเมื่อสร้างเธรด มันมีอินเทอร์เฟซเช่น PrintStackTrace () เพื่อรับข้อมูลเช่นข้อมูลการติดตามสแต็ก
2. ข้อยกเว้น
ข้อยกเว้นและคลาสย่อยของมันเป็นรูปแบบของการขว้างปาที่ชี้ให้เห็นเงื่อนไขที่แอปพลิเคชันที่สมเหตุสมผลต้องการที่จะจับ
3. RuntimeException
RuntimeException เป็น superclass ที่อาจโยนข้อยกเว้นในระหว่างการทำงานปกติของเครื่องเสมือน Java
คอมไพเลอร์ไม่ได้ตรวจสอบข้อยกเว้น RuntimeException ตัวอย่างเช่นเมื่อตัวหารเป็นศูนย์ข้อยกเว้น arithmeticexception จะถูกโยนลงไป RuntimeException เป็น superclass ของ arithmeticexception เมื่อรหัสมีตัวหารของศูนย์มันก็สามารถรวบรวมได้ถ้ามัน "ไม่ได้ถูกโยนผ่านการประกาศโยน" หรือ "ไม่ได้รับการจัดการผ่านการลอง ... จับ ... " นี่คือสิ่งที่เราพูดว่า "คอมไพเลอร์จะไม่ตรวจสอบข้อยกเว้น RuntimeException"!
หากรหัสสร้างข้อยกเว้น RuntimeException จะต้องหลีกเลี่ยงโดยการแก้ไขรหัส ตัวอย่างเช่นหากตัวหารเป็นศูนย์คุณต้องหลีกเลี่ยงสถานการณ์นี้ผ่านรหัส!
4. ข้อผิดพลาด
เช่นข้อยกเว้นข้อผิดพลาดยังเป็นคลาสย่อยของการโยนได้ มันถูกใช้เพื่อระบุปัญหาร้ายแรงที่แอปพลิเคชันที่สมเหตุสมผลไม่ควรพยายามจับและข้อผิดพลาดส่วนใหญ่เป็นเงื่อนไขที่ยอดเยี่ยม
เช่นเดียวกับ RuntimeException คอมไพเลอร์จะไม่ตรวจสอบข้อผิดพลาด
Java แบ่งโครงสร้างที่โยนได้ออกเป็นสามประเภท: ตรวจสอบข้อยกเว้น (ตรวจสอบข้อยกเว้น), ข้อยกเว้นรันไทม์ (RuntimeException) และข้อผิดพลาด (ข้อผิดพลาด)
(1) ข้อยกเว้นรันไทม์
คำจำกัดความ: RuntimeException และคลาสย่อยของมันเรียกว่าข้อยกเว้นรันไทม์
คุณสมบัติ: คอมไพเลอร์ Java จะไม่ตรวจสอบ กล่าวคือเมื่อข้อยกเว้นดังกล่าวอาจเกิดขึ้นในโปรแกรมถ้ามันเป็น "ไม่ได้ถูกโยนผ่านการประกาศการโยน" หรือ "ไม่ได้รับคำสั่งลองจับ" มันจะยังคงถูกรวบรวมและผ่าน ตัวอย่างเช่นข้อยกเว้น arithmeticexception ที่สร้างขึ้นเมื่อตัวหารเป็นศูนย์ข้อยกเว้น indexoutofboundsexception ที่สร้างขึ้นเมื่ออาร์เรย์อยู่นอกขอบเขตข้อยกเว้นพร้อมกันที่เกิดขึ้นพร้อมกันโดยกลไกความล้มเหลวในการทำงานเป็นต้นเป็นข้อยกเว้นรันไทม์ทั้งหมด
แม้ว่าคอมไพเลอร์ Java จะไม่ตรวจสอบข้อยกเว้นรันไทม์ แต่เรายังสามารถประกาศและโยนมันผ่านการโยนหรือจับมันผ่านลองจับ
หากมีการสร้างข้อยกเว้นรันไทม์จะต้องหลีกเลี่ยงโดยการแก้ไขรหัส ตัวอย่างเช่นหากตัวหารเป็นศูนย์คุณต้องหลีกเลี่ยงสถานการณ์นี้ผ่านรหัส!
(2) ตรวจสอบข้อยกเว้น
คำจำกัดความ: คลาสข้อยกเว้นเองและคลาสย่อยอื่น ๆ ในคลาสย่อยของข้อยกเว้นยกเว้น "ข้อยกเว้นรันไทม์" ทั้งหมดถือเป็นข้อยกเว้นที่ตรวจสอบแล้ว
คุณสมบัติ: คอมไพเลอร์ Java จะตรวจสอบ ข้อยกเว้นดังกล่าวได้รับการประกาศและโยนผ่านการโยนหรือถูกจับผ่านการลองจับมิฉะนั้นพวกเขาไม่สามารถรวบรวมได้ ตัวอย่างเช่น ClonenotsupportedException เป็นข้อยกเว้นที่ตรวจสอบแล้ว เมื่อวัตถุถูกโคลนผ่านอินเตอร์เฟส clone () และคลาสที่สอดคล้องกันของวัตถุไม่ได้ใช้อินเตอร์เฟส cloneable clonenotsupportedException จะถูกโยนลง
ข้อยกเว้นที่ถูกตรวจสอบสามารถกู้คืนได้
(3) ข้อผิดพลาด
คำจำกัดความ: คลาสข้อผิดพลาดและคลาสย่อย
คุณสมบัติ: เช่นเดียวกับข้อยกเว้นรันไทม์คอมไพเลอร์จะไม่ตรวจสอบข้อผิดพลาด
ข้อผิดพลาดเกิดขึ้นเมื่อมีทรัพยากรไม่เพียงพอความล้มเหลวของข้อ จำกัด หรือเงื่อนไขอื่น ๆ ที่ไม่สามารถดำเนินการต่อโดยโปรแกรมอื่น ๆ ได้ โปรแกรมเองไม่สามารถแก้ไขข้อผิดพลาดเหล่านี้ได้ ตัวอย่างเช่น VirtualMachineRror เป็นข้อผิดพลาด
ตามอนุสัญญา Java เราไม่ควรใช้คลาสย่อยข้อผิดพลาดใหม่ใด ๆ !
สำหรับสามโครงสร้างข้างต้นเราควรทำข้อยกเว้นหรือข้อผิดพลาดใด คำแนะนำที่ให้ไว้ใน "Java ที่มีประสิทธิภาพ" คือ: ใช้ข้อยกเว้นที่ตรวจสอบสำหรับเงื่อนไขที่สามารถกู้คืนได้และใช้ข้อยกเว้นรันไทม์สำหรับข้อผิดพลาดของโปรแกรม
คำแนะนำหลายประการเกี่ยวกับการจัดการข้อยกเว้น
บทความที่ 1: ใช้ข้อยกเว้นสำหรับสถานการณ์ที่ผิดปกติเท่านั้น
คำแนะนำ: ควรใช้ข้อยกเว้นสำหรับเงื่อนไขที่ผิดปกติเท่านั้นและไม่ควรใช้สำหรับการควบคุมการควบคุมปกติ
คำอธิบายทำโดยการเปรียบเทียบสองรหัสด้านล่าง
รหัส 1
ลอง {int i = 0; ในขณะที่ (จริง) {arr [i] = 0; i ++; }} catch (indexoutofboundsexception e) {} รหัส 2 สำหรับ (int i = 0; i <arr.length; i ++) {arr [i] = 0;} วัตถุประสงค์ของรหัสทั้งสองคือการวนซ้ำมากกว่าอาร์เรย์ ARR และตั้งค่าของแต่ละองค์ประกอบในอาร์เรย์เป็น 0 รหัส 1 สิ้นสุดลงโดยข้อยกเว้นซึ่งดูเหมือนจะยากมากที่จะเข้าใจรหัส 2 สิ้นสุดลงตามขอบเขตอาร์เรย์ เราควรหลีกเลี่ยงการใช้รหัส 1 ด้วยเหตุผลหลักสามประการ:
การออกแบบดั้งเดิมของกลไกข้อยกเว้นสำหรับสถานการณ์ที่ผิดปกติดังนั้นการใช้งาน JVM เพียงไม่กี่ตัวจึงพยายามเพิ่มประสิทธิภาพให้เหมาะสม ดังนั้นค่าใช้จ่ายในการสร้างการขว้างปาและการจับข้อยกเว้นจึงมีราคาแพง
การวางรหัสในการส่งคืนการจับจะป้องกันไม่ให้ JVM ใช้การปรับให้เหมาะสมเฉพาะบางอย่างที่อาจดำเนินการ
รูปแบบมาตรฐานของอาร์เรย์ Traversing ไม่ได้นำไปสู่การตรวจสอบซ้ำซ้อนและการใช้งาน JVM ที่ทันสมัยบางอย่างจะปรับให้เหมาะสม
ในความเป็นจริงโหมดการยกเว้นจะช้ากว่าโหมดมาตรฐานมาก รหัสทดสอบมีดังนี้:
คำแนะนำชั้นเรียนสาธารณะ 1 {ส่วนตัวคงที่ int [] arr = new int [] {1,2,3,4,5}; ขนาด int คงที่ส่วนตัว = 10,000; โมฆะคงที่สาธารณะหลัก (String [] args) {Long S1 = System.currentTimeMillis (); สำหรับ (int i = 0; i <size; i ++) endbyRange (arr); Long E1 = System.currentTimeMillis (); System.out.println ("endbyRange Time:"+(E1-S1)+"MS"); Long S2 = System.currentTimeMillis (); สำหรับ (int i = 0; i <size; i ++) endbyexception (arr); Long E2 = System.currentTimeMillis (); System.out.println ("เวลา endbyexception:"+(e2-s2)+"ms"); } // traverse arr array: โมฆะคงที่ส่วนตัว endbyexception (int [] arr) {ลอง {int i = 0; ในขณะที่ (จริง) {arr [i] = 0; i ++; //system.out.println("endbyRange: arr ["+i+"] = "+arr [i]); }} catch (indexoutofboundsexception e) {}} // โอนอาร์เรย์ Arrray: โมฆะคงที่ส่วนตัว endbyRange (int [] arr) {สำหรับ (int i = 0; i <arr.length; i ++) {arr [i] = 0; //system.out.println("endbyexception: arr ["+i+"] = "+arr [i]); - ผลการทำงาน:
เวลา endbyRange: 8MSENDBYEXPECTION TIME: 16MS
ผลการวิจัยแสดงให้เห็นว่าความเร็วในการสำรวจข้อยกเว้นนั้นช้ากว่าการสำรวจอาร์เรย์ในแบบธรรมดามาก!
บทความที่ 2: ใช้ข้อยกเว้นที่ตรวจสอบสำหรับเงื่อนไขที่กู้คืนได้และใช้ข้อยกเว้นรันไทม์สำหรับข้อผิดพลาดของโปรแกรม
| ผิดปกติ | อธิบาย |
|---|---|
| ข้อยกเว้นรันไทม์ | คลาส RuntimeException และคลาสย่อยของมันเรียกว่าข้อยกเว้นรันไทม์ |
| ข้อยกเว้นที่ตรวจสอบ | คลาสข้อยกเว้นเองรวมถึงคลาสย่อยอื่น ๆ ยกเว้น "ข้อยกเว้นรันไทม์" เป็นข้อยกเว้นที่ตรวจสอบทั้งหมด |
ความแตกต่างคือคอมไพเลอร์ Java ตรวจสอบ "ข้อยกเว้นตรวจสอบ" และไม่ได้ตรวจสอบ "ข้อยกเว้นรันไทม์"
กล่าวคือสำหรับข้อยกเว้นที่ตรวจสอบจะมีการประกาศและโยนผ่านการโยนหรือจับผ่านการลองจับมิฉะนั้นจะไม่สามารถรวบรวมได้ สำหรับข้อยกเว้นรันไทม์หากพวกเขา "ไม่ได้ถูกโยนผ่านการประกาศโยน" หรือ "ไม่ได้รับคำสั่งลองจับ" พวกเขาจะยังคงถูกรวบรวมและผ่าน แน่นอนแม้ว่าคอมไพเลอร์ Java จะไม่ตรวจสอบข้อยกเว้นรันไทม์ แต่เรายังสามารถอธิบายข้อยกเว้นผ่านการโยนหรือจับมันผ่านลองจับ
Rithmeticexception (ตัวอย่างเช่นตัวหารคือ 0), indexoutofboundsexception (ตัวอย่างเช่นอาร์เรย์นอกขอบเขต) ฯลฯ ล้วนเป็นข้อยกเว้นรันไทม์ทั้งหมด สำหรับข้อยกเว้นนี้เราควรหลีกเลี่ยงโดยการแก้ไขรหัส สำหรับข้อยกเว้นที่ตรวจสอบโปรแกรมสามารถกู้คืนเพื่อเรียกใช้ผ่านการประมวลผล ตัวอย่างเช่นสมมติว่าเนื่องจากผู้ใช้ไม่ได้จัดเก็บจำนวนการโทรที่เพียงพอเขาจะล้มเหลวเมื่อพยายามโทรหาสายจ่าย ดังนั้นการโยนข้อยกเว้นที่ตรวจสอบ
ข้อ 3: หลีกเลี่ยงการใช้ข้อยกเว้นที่ตรวจสอบโดยไม่จำเป็น
"ข้อยกเว้นเซ็นเซอร์" เป็นคุณสมบัติที่ดีของ Java ซึ่งแตกต่างจากรหัสส่งคืน "ข้อยกเว้นตรวจสอบ" บังคับให้โปรแกรมเมอร์จัดการกับเงื่อนไขข้อยกเว้นปรับปรุงความน่าเชื่อถือของโปรแกรมอย่างมาก
อย่างไรก็ตามการใช้ข้อยกเว้นที่ตรวจสอบมากเกินไปสามารถทำให้ API ไม่สะดวกมาก หากวิธีการโยนข้อยกเว้นที่ตรวจสอบอย่างน้อยหนึ่งรายการรหัสที่เรียกว่าวิธีการจะต้องจัดการข้อยกเว้นเหล่านี้ในบล็อกคำสั่งจับอย่างน้อยหนึ่งรายการหรือพวกเขาจะต้องถูกโยนผ่านการประกาศโยน ไม่ว่าจะเป็นการจัดการผ่านการจับหรือโยนผ่านการประกาศโยนมันเพิ่มภาระที่ไม่ได้รับการรับรองให้กับโปรแกรมเมอร์
ต้องปฏิบัติตามเงื่อนไขสองประการสำหรับ "ข้อยกเว้นที่ตรวจสอบ": ก่อนอื่นแม้ว่า API จะใช้อย่างถูกต้อง แต่ก็ไม่สามารถป้องกันการเกิดขึ้นของเงื่อนไขข้อยกเว้นได้ ประการที่สองเมื่อมีการสร้างข้อยกเว้นโปรแกรมเมอร์ที่ใช้ API สามารถดำเนินการที่เป็นประโยชน์ในการประมวลผลโปรแกรม
บทความ 4: ลองใช้ข้อยกเว้นมาตรฐาน
การใช้รหัสซ้ำมีค่าควรแก่การสนับสนุนนี่เป็นกฎทั่วไปและข้อยกเว้นก็ไม่มีข้อยกเว้น มีประโยชน์หลายประการในการนำข้อยกเว้นที่มีอยู่กลับมาใช้ใหม่:
อันดับแรกมันทำให้ API ของคุณเรียนรู้และใช้งานง่ายขึ้นเพราะมันสอดคล้องกับสำนวนที่โปรแกรมเมอร์คุ้นเคย
ประการที่สองสำหรับโปรแกรมที่ใช้ API เหล่านี้พวกเขาสามารถอ่านได้ดีกว่าเพราะพวกเขาไม่ได้เต็มไปด้วยข้อยกเว้นที่ไม่คุ้นเคยกับโปรแกรมเมอร์
ประการที่สามคลาสข้อยกเว้นที่น้อยลงการใช้หน่วยความจำให้เล็กลงและเวลาที่ใช้ในการพิมพ์ชั้นเรียนเหล่านี้มีขนาดเล็กลง
ข้อยกเว้นมาตรฐาน Java หลายข้อมักจะใช้ข้อยกเว้น ตารางต่อไปนี้:
| ผิดปกติ | ใช้โอกาส |
|---|---|
| ผิดกฎหมาย | ค่าพารามิเตอร์ไม่เหมาะสม |
| ผิดกฎหมาย | พารามิเตอร์ไม่เหมาะสม |
| nullpointerexception | เมื่อ null ถูกปิดใช้งานค่าพารามิเตอร์จะเป็นโมฆะ |
| indexoutofboundsexception | ตัวห้อยข้ามขอบเขต |
| พร้อมกันกับ Exception | เมื่อห้ามการดัดแปลงพร้อมกันวัตถุจะตรวจจับการปรับเปลี่ยนพร้อมกัน |
| unsupportedoperationexception | วิธีการที่วัตถุไม่สนับสนุนคำขอของลูกค้า |
แม้ว่าพวกเขาจะเป็นข้อยกเว้นที่นำกลับมาใช้ใหม่มากที่สุดของไลบรารีแพลตฟอร์ม Java จนถึงปัจจุบัน แต่ข้อยกเว้นอื่น ๆ ก็สามารถนำกลับมาใช้ใหม่ได้ภายใต้เงื่อนไขใบอนุญาต ตัวอย่างเช่นหากคุณต้องการใช้วัตถุทางคณิตศาสตร์เช่นตัวเลขที่ซับซ้อนหรือเมทริกซ์มันจะเหมาะสมมากที่จะนำ arithmeticexception กลับมาใช้ใหม่และ NumberFormatexception หากข้อยกเว้นตรงตามความต้องการของคุณอย่าลังเลที่จะใช้ แต่คุณต้องตรวจสอบให้แน่ใจว่าเงื่อนไขของการขว้างข้อยกเว้นนั้นสอดคล้องกับเงื่อนไขที่อธิบายไว้ในเอกสารสำหรับข้อยกเว้น การใช้ซ้ำนี้จะต้องขึ้นอยู่กับความหมายไม่ใช่ในชื่อ!
ในที่สุดอย่าลืมชัดเจนว่าไม่มีกฎใด ๆ ที่ต้องปฏิบัติตามเมื่อเลือกข้อยกเว้นที่จะนำกลับมาใช้ใหม่ ตัวอย่างเช่นการพิจารณากรณีของวัตถุการ์ดสมมติว่ามีวิธีการจัดการการดำเนินการและพารามิเตอร์ (HARMIZE) คือจำนวนการ์ดที่จะได้รับในมือ สมมติว่าผู้โทรผ่านค่าในพารามิเตอร์นี้มากกว่าจำนวนการ์ดที่เหลือสำหรับสำรับทั้งหมด จากนั้นสถานการณ์นี้สามารถตีความได้ว่าเป็นข้อผิดพลาดที่ผิดกฎหมาย (มูลค่าของการจับมือกันมากเกินไป) หรือผิดกฎหมาย stateException (วัตถุการ์ดมีการ์ดน้อยเกินไปเมื่อเทียบกับคำขอของลูกค้า)
ข้อ 5: ข้อยกเว้นที่ถูกโยนควรเหมาะสมสำหรับนามธรรมที่สอดคล้องกัน
สถานการณ์นี้สามารถครอบงำได้หากข้อยกเว้นที่ถูกโยนโดยวิธีการไม่มีความสัมพันธ์ที่ชัดเจนกับงานที่ดำเนินการ สิ่งนี้มักจะเกิดขึ้นเมื่อวิธีการผ่านข้อยกเว้นที่ถูกโยนลงโดยนามธรรมระดับต่ำ เมื่อสิ่งนี้เกิดขึ้นมันไม่เพียง แต่สับสน แต่ยังรวมถึง "มลพิษ" API ระดับสูง
เพื่อหลีกเลี่ยงปัญหานี้การใช้งานระดับสูงควรจับข้อยกเว้นระดับต่ำและโยนข้อยกเว้นที่สามารถแนะนำได้ตามนามธรรมระดับสูง การปฏิบัตินี้เรียกว่า "การแปลข้อยกเว้น"
ตัวอย่างเช่นกรอบการรวบรวม Java Framework AbstractextiveList GET () มีดังนี้ (ขึ้นอยู่กับ JDK1.7.0_40):
สาธารณะ e get (int index) {ลอง {return listiterator (ดัชนี) .next (); } catch (nosuchelementException exc) {โยน indexoutofboundsexception ใหม่ ("ดัชนี:"+ดัชนี); -listiterator (ดัชนี) จะส่งคืนวัตถุ listiterator การเรียกวิธีการถัดไป () ของวัตถุอาจส่งข้อยกเว้น nosuchelementException ในวิธีการรับ () การโยนข้อยกเว้น nosuchelementexception จะทำให้เกิดความสับสน ดังนั้นรับ () จับภาพ nosuchelementexception และโยนข้อยกเว้น indexoutofboundsexception นั่นคือมันเทียบเท่ากับการแปลง nosuchelementexception เป็นข้อยกเว้น indexoutofboundsexception
บทความที่ 6: ข้อยกเว้นที่ถูกโยนโดยแต่ละวิธีจะต้องมีการบันทึกไว้
ในการประกาศข้อยกเว้นที่ตรวจสอบแยกต่างหากและใช้แท็ก @throws ของ javadoc เพื่อบันทึกเงื่อนไขอย่างถูกต้องสำหรับแต่ละข้อยกเว้นที่จะโยน
หากมีหลายวิธีในชั้นเรียนที่มีข้อยกเว้นเดียวกันด้วยเหตุผลเดียวกันก็เป็นที่ยอมรับได้ที่จะทำเอกสารสำหรับข้อยกเว้นนี้ในความคิดเห็นของเอกสารของคลาสนั้นแทนที่จะบันทึกเป็นรายบุคคลสำหรับแต่ละวิธี
บทความ 7: รวมถึงความล้มเหลวในรายละเอียดข้อความรับข้อความ
ในระยะสั้นเมื่อเราปรับแต่งหรือโยนข้อยกเว้นเราควรรวมข้อมูลที่เกี่ยวข้องกับความล้มเหลว
เมื่อโปรแกรมล้มเหลวเนื่องจากข้อยกเว้นที่ไม่ถูกต้องระบบจะพิมพ์ร่องรอยสแต็กโดยอัตโนมัติ มีการแสดงสตริงของข้อยกเว้นในแทร็กสแต็ก โดยทั่วไปจะมีชื่อคลาสของคลาสข้อยกเว้นพร้อมกับข้อความโดยละเอียดที่ตามมา
มาตรา 8: มุ่งมั่นที่จะรักษาอะตอมในความล้มเหลว
เมื่อวัตถุโยนข้อยกเว้นเราคาดหวังเสมอว่าวัตถุนั้นยังคงอยู่ในสถานะที่กำหนดไว้อย่างดี สิ่งนี้มีความสำคัญอย่างยิ่งสำหรับข้อยกเว้นที่ตรวจสอบเนื่องจากผู้โทรมักคาดว่าจะกู้คืนจากข้อยกเว้นที่ตรวจสอบ
โดยทั่วไปการเรียกใช้วิธีที่ล้มเหลวควรเก็บวัตถุไว้ใน "สถานะก่อนที่จะเรียกว่า" วิธีการที่มีคุณลักษณะดังกล่าวเรียกว่า "ความล้มเหลวอะตอม" สามารถเข้าใจได้ว่าความล้มเหลวยังคงรักษาความเป็นอะตอม มีหลายวิธีที่วัตถุจะรักษา "ความล้มเหลวของอะตอม":
(1) ออกแบบวัตถุที่ไม่สามารถใช้งานได้
(2) สำหรับวิธีการที่ดำเนินการกับวัตถุที่ไม่แน่นอนวิธีที่พบได้บ่อยที่สุดในการรับ "ความผิดพลาดที่ล้มเหลว" คือการตรวจสอบความถูกต้องของพารามิเตอร์ก่อนดำเนินการ ดังนี้ (วิธีป๊อปใน stack.java):
วัตถุสาธารณะป๊อป () {ถ้า (ขนาด == 0) โยน emptystackexception ใหม่ (); ผลลัพธ์ของวัตถุ = องค์ประกอบ [-ขนาด]; องค์ประกอบ [ขนาด] = null; ผลตอบแทนผลลัพธ์;} (3) คล้ายกับวิธีก่อนหน้าการประมวลผลการคำนวณสามารถปรับได้เพื่อให้ความล้มเหลวใด ๆ ที่เป็นไปได้ของชิ้นส่วนการคำนวณเกิดขึ้นก่อนที่สถานะวัตถุจะถูกแก้ไข
(4) เขียนรหัสการกู้คืนเพื่ออธิบายความล้มเหลวในระหว่างการดำเนินการและเพื่อให้วัตถุหมุนกลับไปที่สถานะก่อนที่จะเริ่มการผ่าตัด
(5) ทำการดำเนินการในสำเนาชั่วคราวของวัตถุและหลังจากการดำเนินการเสร็จสมบูรณ์แล้วให้คัดลอกผลลัพธ์ในสำเนาชั่วคราวไปยังวัตถุต้นฉบับ
ในขณะที่ "การรักษาอะตอมที่ล้มเหลวของวัตถุ" เป็นเป้าหมายที่ต้องการ แต่ก็เป็นไปไม่ได้เสมอไป ตัวอย่างเช่นหากหลายเธรดพยายามเข้าถึงวัตถุพร้อมกันโดยไม่มีกลไกการซิงโครไนซ์ที่เหมาะสมวัตถุอาจถูกทิ้งไว้ในสถานะที่ไม่สอดคล้องกัน
แม้ในสถานการณ์ที่ "ล้มเหลวอะตอม" สามารถทำได้ แต่ก็ไม่ได้คาดหวังเสมอไป สำหรับการดำเนินการบางอย่างสามารถเพิ่มค่าใช้จ่ายหรือความซับซ้อนได้อย่างมีนัยสำคัญ
กฎทั่วไปคือ: เป็นส่วนหนึ่งของข้อกำหนดวิธีการไม่ควรมีข้อยกเว้นควรเปลี่ยนสถานะของวัตถุก่อนที่จะเรียกวิธีการ หากกฎนี้ถูกละเมิดเอกสาร API ควรระบุอย่างชัดเจนว่าจะระบุว่าวัตถุใดจะอยู่ใน
ข้อ 9: อย่าเพิกเฉยต่อข้อยกเว้น
เมื่อนักออกแบบ API ประกาศว่าวิธีการจะโยนข้อยกเว้นพวกเขากำลังพยายามแสดงให้เห็นถึงบางสิ่งบางอย่าง ดังนั้นโปรดอย่าเพิกเฉย! รหัสที่จะละเว้นข้อยกเว้นมีดังนี้:
ลอง {... } catch (someException e) {} บล็อกการจับที่ว่างเปล่าจะทำให้ข้อยกเว้นไม่สามารถบรรลุวัตถุประสงค์ได้ จุดประสงค์ของข้อยกเว้นคือบังคับให้คุณจัดการกับเงื่อนไขที่ผิดปกติ การเพิกเฉยต่อข้อยกเว้นก็เหมือนกับการเพิกเฉยต่อสัญญาณสัญญาณเตือนไฟไหม้ - หากสัญญาณสัญญาณเตือนไฟไหม้ถูกปิดแล้วจะไม่มีใครเห็นสัญญาณสัญญาณเตือนไฟไหม้เมื่อเกิดไฟไหม้จริง ดังนั้นอย่างน้อยบล็อก catch ควรมีคำอธิบายที่อธิบายว่าทำไมจึงเหมาะสมที่จะเพิกเฉยต่อข้อยกเว้นนี้