ลองเป็นเหมือนเครือข่ายซึ่งทำให้ข้อยกเว้นทั้งหมดถูกโยนโดยรหัสในลอง {} จากนั้นส่งข้อยกเว้นให้กับรหัสใน catch {} สำหรับการประมวลผล ในที่สุดก็เรียกใช้รหัสในที่สุด ไม่ว่าจะมีข้อยกเว้นในรหัสในการลองหรือไม่และการจับจับจับข้อยกเว้นหรือไม่รหัสในที่สุดจะถูกดำเนินการ
ในขณะที่โปรเซสเซอร์ที่ตั้งไว้ล่วงหน้าโดยระบบระยะเวลาการดำเนินการ Java นั้นมีประโยชน์สำหรับการดีบัก แต่คุณมักจะต้องการจัดการกับข้อยกเว้นด้วยตัวคุณเอง มีข้อดีสองประการในการทำสิ่งนี้: ก่อนอื่นจะช่วยให้คุณสามารถแก้ไขข้อผิดพลาดได้ ประการที่สองมันสามารถป้องกันไม่ให้โปรแกรมจากการเลิกจ้างโดยอัตโนมัติ เมื่อใดก็ตามที่เกิดข้อผิดพลาดหากโปรแกรมของคุณหยุดและพิมพ์แทร็กสแต็กผู้ใช้ส่วนใหญ่จะสับสน โชคดีที่คุณสามารถหลีกเลี่ยงสถานการณ์นี้ได้อย่างง่ายดาย
หากต้องการระวังและจัดการกับข้อผิดพลาดระยะเวลาการดำเนินการเพียงใส่รหัสที่คุณต้องการตรวจสอบในบล็อกลอง ทันทีหลังจากบล็อกลองระบุตัวอย่างการจับข้อผิดพลาดประเภทข้อยกเว้นที่คุณต้องการจับในประโยคจับ:
ลอง {code;
ตัวอย่างเช่น:
นำเข้า java.io.*; // การเรียกแพ็คเกจ IO public public class simplecharinout {โมฆะคงที่สาธารณะหลัก (สตริง args []) {char ch = ''; // การกำหนดตัวละคร ch เป็น 'system.out.prin tln (" โปรดป้อนอักขระ "); // เปิด Enter A อักขระโปรดลองบนหน้าจอ {// โปรดใส่รหัสโปรแกรมที่คุณต้องการตรวจสอบในบล็อกลอง ทันทีหลังจากลองบล็อกให้ระบุรูปแบบข้อยกเว้นที่คุณต้องการจับในข้อจับ catch CH = (char) system.in.read (); // กำหนดอักขระที่ป้อนจากคีย์บอร์ดไปยัง ch} catch (ioexception e) // หากมีข้อผิดพลาดในรหัสด้านบนคุณจะจับ {} ที่นี่; // ไม่มีการดำเนินการหลังจากระบบข้อผิดพลาด. อักขระหน้าจอ: // และค่าของ CH}}
เมื่อเราเขียน java ลอง .. จับเรามักจะต้องเพิ่มคำสั่งในที่สุดเพื่อปิดแหล่งข้อมูล IO บางอย่างเช่น
InputStream คือ; ลอง {is = openInputStream (); }}
แต่เมื่อใช้รูปแบบนี้แม้แต่ทหารผ่านศึก Java บางครั้งก็ทำผิดพลาด ตัวอย่างเช่นในรหัสข้างต้นเมื่อฟังก์ชั่น OpenInputStream () โยนข้อยกเว้นในระหว่างการดำเนินการค่าของตัวแปรยังคงเป็นโมฆะ ดังนั้นจึงไม่สามารถจับได้โดยบล็อกจับ แต่ถูกโยนลงไปที่เลเยอร์การโทรโดยตรง โดยส่วนตัวแล้วฉันคิดว่าวิธีการเขียนที่สง่างามมากขึ้นคือการเรียกใช้วิธี ioutils.closequitely () โดยตรงโดยแพ็คเกจ Commons-iO เพื่อปิดสตรีม (หรือห่อหุ้มวิธีการใกล้ชิด () ด้วยตัวคุณเอง)
มีข้อได้เปรียบอีกประการหนึ่งของการใช้วิธีการเขียนนี้ซึ่งก็คือไม่ใช่เรื่องง่ายที่จะทำผิดพลาดเมื่อปิดแหล่งข้อมูล IO หลายรายการเช่นรหัสต่อไปนี้:
InputStream คือ OutputStream OS; ลอง {IS = OpenInputStream (); if (os! = null) os.close ();} catch (ioexception e) {}}
เมื่อเกิดข้อผิดพลาดใน IS.CLOSE (), OS.CLOSE () ไม่สามารถดำเนินการได้ส่งผลให้ทรัพยากรอ้างอิงโดยระบบปฏิบัติการที่ไม่ได้ถูกปล่อยออกมา
บางทีออราเคิลก็คิดว่าการลองแบบนี้ ... จับ ... ในที่สุดรหัสหม้อต้มไม่จำเป็นดังนั้นฉันจึงทำการปรับเปลี่ยนบางส่วนในประโยคการลองใน JDK 7 โดยกำจัดการเขียนโค้ดที่ปิดทรัพยากรด้วยตนเอง ดูกะทัดรัดและง่ายขึ้น ตัวอย่างเช่นรหัสด้านบนสามารถเปลี่ยนเป็น:
ลอง (inputStream คือ = openInputStream (); OutputStream OS = OpenOutStream ();) {// ทำอะไร} catch (ioException e) {E.printStacetrace (e);}
Oracle เรียกคำสั่ง try (.. ) ที่นี่คำสั่ง try-with-resource ควรสังเกตว่าวัตถุที่อ้างอิงโดยตัวแปรในการลอง (.. ) ต้องเป็นอินสแตนซ์ที่ใช้อินเตอร์เฟส java.io.autoclosable กล่าวคือทรัพยากรในคำสั่ง Try-With-Resource ไม่ จำกัด เฉพาะทรัพยากร IO
ที่นี่มีความจำเป็นที่จะต้องให้คำอธิบายเพิ่มเติมสำหรับรายละเอียดบางอย่างของคำสั่ง try-with-resource:
JDK ทำให้มั่นใจได้ว่าวิธีการปิด () ของทรัพยากรทั้งหมดเรียกว่าโดยไม่คำนึงว่าวิธีการปิด () จะมีข้อยกเว้นหรือไม่และลำดับของการโทรกลับถูกย้อนกลับจากคำสั่งของการประกาศทรัพยากร
ข้อยกเว้นทั้งหมดที่ถูกโยนทิ้งในคำสั่ง Try-With-Resource จะถูกจับได้ หากมีการโยนข้อยกเว้นหลายอย่างข้อยกเว้นที่ตามมาจะถูกระงับ ข้อยกเว้นที่ถูกระงับสามารถรับได้โดยการเรียก getSuppressed () ที่กำหนดโดยคลาสที่สามารถขยายได้
ตัวอย่างด้านบน
เมื่อออกจากการลอง .. บล็อก ในข้อยกเว้นที่โยนโดย OS.Close () คุณสามารถรับข้อยกเว้นที่ถูกโยนโดย IS.close () ผ่านวิธี getSuppressed ()
หากมีการเรียก iOException เมื่อเรียกว่า OpenInputStream () แล้ว OpenOutputStream () จะไม่ถูกเรียก, OS.Close () และ IS.Close () จะไม่ถูกเรียกและ catch Block จับการโยนเมื่อเรียก OpenInputStream ()
หาก IOException เกิดขึ้น (ระบุโดยโทเค็น E1) แล้ว IS.close () จะยังคงถูกเรียก ข้อยกเว้นที่ถูกจับโดยบล็อกคือ E1
นอกเหนือจากการปรับปรุงบล็อกลอง JDK 7 ยังช่วยลดความซับซ้อนของส่วนที่จับได้ ตัวอย่างเช่น:
ลอง (inputStream คือ = openInputStream (); OutputStream OS = OpenOutStream ();) {// ทำอะไร} catch (iOException | XMLParSeException | XPathException E) {E.PrintStacetrace (E);};
นอกจากนี้เมื่อคุณรีทวีตข้อยกเว้นหลายข้อคุณไม่จำเป็นต้องกำหนดประเภทข้อยกเว้นในรายละเอียดอีกต่อไป คุณเพียงแค่ต้องประกาศข้อยกเว้นที่ต้องโยนเมื่อมีการกำหนดวิธีการ ตัวอย่างเช่น
// แม้ว่าจะมีการใช้ข้อยกเว้นที่นี่เพื่อให้ตรงกับ IOException ที่ถูกโยนลงมา แต่คอมไพเลอร์รู้ว่าข้อยกเว้นจริง ๆ ) {โยน e;}}
PS: ฉันไม่สามารถนึกถึงประโยชน์ใด ๆ ที่คุณลักษณะนี้จะนำมา
JDK 7 มีคุณสมบัติทางไวยากรณ์ใหม่ที่น่าสนใจอื่น ๆ เช่นตัวอักษรไบนารีการแบ่งส่วนของตัวเลขยาวที่มีขีดล่างประเภทการอนุมานของพารามิเตอร์ทั่วไปสวิตช์รองรับการจับคู่สตริง ฯลฯ ตอนนี้ JDK 8 ได้แนะนำคุณสมบัติที่มีประโยชน์บางอย่าง โดยไม่คำนึงถึงความเข้ากันได้ย้อนหลังการใช้คุณสมบัติไวยากรณ์บางอย่างที่เหมาะสมและยืดหยุ่นสามารถทำให้รหัสของเราดูชัดเจนขึ้นและกระชับมากขึ้นในระดับหนึ่ง