1. ประเภทของข้อยกเว้น

ข้อยกเว้นทั้งหมดแบ่งออกเป็น 4 ประเภทซึ่งเป็นคลาสที่สืบทอดซึ่งกันและกัน
Throwable
ระดับ
คลาสพื้นฐานสำหรับข้อยกเว้นทั้งหมดคือThrowable
คลาส คลาสThrowable
ประกอบด้วยโค้ดที่เขียน call stack ปัจจุบัน (stack trace ของเมธอดปัจจุบัน) ไปยังอาร์เรย์ เราจะเรียนรู้ว่าการติดตามสแต็กคืออะไรในภายหลัง
ตัว ดำเนิน การโยนสามารถยอมรับวัตถุที่มาจากThrowable
ชั้นเรียน เท่านั้น และแม้ว่าในทางทฤษฎีแล้วคุณสามารถเขียนโค้ดได้ แต่throw new Throwable();
มักจะไม่มีใครทำสิ่งนี้ จุดประสงค์หลักของThrowable
คลาสคือการมีคลาสพาเรนต์เดียวสำหรับข้อยกเว้นทั้งหมด
Error
ระดับ
คลาสยกเว้นถัดไปคือError
คลาสซึ่งสืบทอดThrowable
คลาส โดยตรง เครื่อง Java สร้างอ็อบเจกต์ของคลาสError
(และคลาสรอง) เมื่อเกิดปัญหาร้ายแรง ตัวอย่างเช่น ฮาร์ดแวร์ทำงานผิดปกติ หน่วยความจำไม่เพียงพอ เป็นต้น
โดยปกติแล้ว ในฐานะโปรแกรมเมอร์คุณไม่สามารถทำอะไรได้ในสถานการณ์ที่เกิดข้อผิดพลาด (ซึ่งError
ควรจะเกิดขึ้น) ในโปรแกรม ข้อผิดพลาดเหล่านี้ร้ายแรงเกินไป สิ่งที่คุณทำได้คือแจ้งให้ผู้ใช้ทราบว่าโปรแกรมขัดข้อง และ/หรือเขียนข้อมูลที่ทราบทั้งหมดเกี่ยวกับข้อผิดพลาดลงในบันทึกของโปรแกรม
Exception
ระดับ
และ คลาสสำหรับข้อผิดพลาดทั่วไปที่เกิด Exception
ขึ้นRuntimeException
ในการทำงานของเมธอดต่างๆ เป้าหมายของการโยนข้อยกเว้นแต่ละครั้งคือการถูกcatch
บล็อกที่รู้วิธีจัดการอย่างถูกต้อง
เมื่อเมธอดไม่สามารถทำงานให้เสร็จได้ด้วยเหตุผลบางประการ เมธอดควรแจ้งเมธอดการโทรทันทีโดยส่งข้อยกเว้นประเภทที่เหมาะสม
กล่าวอีกนัยหนึ่ง ถ้าตัวแปรเท่ากับnull
เมธอดจะโยนค่าNullPointerException
. หากมีการส่งผ่านอาร์กิวเมนต์ที่ไม่ถูกต้องไปยังเมธอด มันจะโยนไฟล์InvalidArgumentException
. หากเมธอดนั้นหารด้วยศูนย์โดยไม่ตั้งใจ มันจะโยนไฟล์ArithmeticException
.
RuntimeException
ระดับ
RuntimeExceptions
เป็นส่วนย่อยExceptions
ของ เราอาจพูดได้ด้วยซ้ำว่าRuntimeException
เป็นข้อยกเว้นธรรมดารุ่นเล็ก ( Exception
) — มีการกำหนดข้อกำหนดและข้อจำกัดน้อยลงสำหรับข้อยกเว้นดังกล่าว
คุณจะได้เรียนรู้ความแตกต่างระหว่างException
และRuntimeException
ในภายหลัง
2. Throws
: ตรวจสอบข้อยกเว้น

ข้อยกเว้น Java ทั้งหมดแบ่งออกเป็น 2 ประเภท: ทำเครื่องหมายและไม่ได้ทำเครื่องหมาย
ข้อยกเว้นทั้งหมดที่สืบทอดRuntimeException
หรือError
ถือเป็นข้อยกเว้นที่ไม่ได้ตรวจสอบ ข้อยกเว้นอื่นๆ ทั้งหมดได้ รับการตรวจสอบ แล้ว
20 ปีหลังจากเปิดตัวข้อยกเว้นที่ตรวจสอบแล้ว โปรแกรมเมอร์ Java เกือบทุกคนคิดว่าสิ่งนี้เป็นข้อบกพร่อง ในเฟรมเวิร์กสมัยใหม่ยอดนิยม 95% ของข้อยกเว้นทั้งหมดไม่ถูกเลือก ภาษา C# ซึ่งเกือบจะคัดลอก Java ทุกประการ ไม่ได้เพิ่มข้อยกเว้นที่ตรวจสอบแล้ว
อะไรคือข้อแตกต่างที่สำคัญระหว่างข้อยกเว้นที่ตรวจสอบและไม่ได้ตรวจสอบ
มีข้อกำหนดเพิ่มเติมสำหรับข้อยกเว้นที่ตรวจสอบ พูดโดยคร่าว ๆ คือ:
ข้อกำหนด 1
ถ้าเมธอดส่งข้อยกเว้นที่ตรวจสอบจะ ต้อง ระบุประเภทของข้อยกเว้นในลายเซ็น ด้วยวิธีนี้ ทุกเมธอดที่เรียกใช้จะทราบว่า "ข้อยกเว้นที่มีความหมาย" นี้อาจเกิดขึ้นในนั้น
ระบุ ข้อยกเว้น ที่ตรวจสอบหลังพารามิเตอร์เมธอดหลังthrows
คีย์เวิร์ด (อย่าใช้throw
คีย์เวิร์ดโดยไม่ได้ตั้งใจ) ดูเหมือนว่า:
type method (parameters) throws exception
ตัวอย่าง:
ตรวจสอบข้อยกเว้น | ข้อยกเว้นที่ไม่ได้ตรวจสอบ |
---|---|
|
|
ในตัวอย่างด้านขวา โค้ดของเราแสดง ข้อยกเว้น ที่ไม่ได้ตรวจสอบ — ไม่จำเป็นต้องดำเนินการใดๆ เพิ่มเติม ในตัวอย่างทางด้านซ้าย เมธอดจะส่ง ข้อยกเว้น ที่ตรวจสอบดังนั้นthrows
คีย์เวิร์ดจึงถูกเพิ่มลงในลายเซ็นเมธอดพร้อมกับประเภทของข้อยกเว้น
หากเมธอดคาดว่าจะส่ง ข้อยกเว้น ที่ตรวจสอบ หลายรายการ จะต้องระบุทั้งหมดหลังthrows
คำสำคัญ โดยคั่นด้วยเครื่องหมายจุลภาค ลำดับไม่สำคัญ ตัวอย่าง:
public void calculate(int n) throws Exception, IOException
{
if (n == 0)
throw new Exception("n is null!");
if (n == 1)
throw new IOException("n is 1");
}
ข้อกำหนด 2
หากคุณเรียกใช้เมธอดที่มีการตรวจสอบข้อยกเว้นในลายเซ็นคุณจะไม่สามารถเพิกเฉยต่อข้อเท็จจริงที่ว่าเมธอดนั้นโยนทิ้งได้
คุณต้องจับข้อยกเว้นดังกล่าวทั้งหมดโดยเพิ่มcatch
บล็อกสำหรับแต่ละรายการ หรือโดยการเพิ่มในthrows
ส่วนคำสั่งสำหรับวิธีการของคุณ
เหมือนกับว่าเรากำลังพูดว่า " ข้อยกเว้นเหล่านี้สำคัญมากที่เราจะต้องจับมันให้ได้ และถ้าเราไม่รู้ว่าจะจัดการกับมันอย่างไร ใครก็ตามที่อาจเรียกใช้วิธีการของเรา จะต้องได้รับแจ้งว่าข้อยกเว้นดังกล่าวสามารถเกิดขึ้นได้ในนั้น
ตัวอย่าง:
ลองนึกภาพว่าเรากำลังเขียนวิธีการสร้างโลกที่มีมนุษย์อาศัยอยู่ จำนวนคนเริ่มต้นจะถูกส่งผ่านเป็นอาร์กิวเมนต์ เราจึงต้องเพิ่มข้อยกเว้นหากมีคนน้อยเกินไป
สร้างโลก | บันทึก |
---|---|
|
เมธอดนี้อาจมี ข้อยกเว้น ที่ตรวจสอบแล้ว สอง รายการ:
|
การเรียกใช้เมธอดนี้สามารถจัดการได้ 3 วิธี:
1. อย่าจับข้อยกเว้นใด ๆ
สิ่งนี้มักทำเมื่อวิธีการนี้ไม่ทราบวิธีจัดการกับสถานการณ์อย่างเหมาะสม
รหัส | บันทึก |
---|---|
|
เมธอดการโทรไม่จับข้อยกเว้นและต้องแจ้งให้ผู้อื่นทราบ: มันเพิ่มเข้าไปในthrows อนุประโยค ของมันเอง |
2. จับข้อยกเว้นบางประการ
เราจัดการกับข้อผิดพลาดที่เราจัดการได้ แต่อันที่เราไม่เข้าใจก็โยนไปตามวิธีการเรียก ในการทำเช่นนี้ เราจำเป็นต้องเพิ่มชื่อของพวกเขาในส่วนคำสั่งโยน:
รหัส | บันทึก |
---|---|
|
ผู้โทรจับข้อยกเว้นที่เลือกไว้เพียงข้อเดียว — LonelyWorldException ต้องเพิ่มข้อยกเว้นอื่นๆ ลงในลายเซ็น โดยระบุหลังthrows คำหลัก |
3. จับข้อยกเว้นทั้งหมด
หากเมธอดไม่ส่งข้อยกเว้นไปยังเมธอดการโทร แสดงว่าเมธอดการโทรนั้นมั่นใจเสมอว่าทุกอย่างทำงานได้ดี และจะไม่สามารถดำเนินการใด ๆ เพื่อแก้ไขสถานการณ์พิเศษได้
รหัส | บันทึก |
---|---|
|
ข้อยกเว้นทั้งหมดถูกจับได้ในวิธีนี้ ผู้โทรจะได้มั่นใจว่าทุกอย่างผ่านไปด้วยดี |
3. จับข้อยกเว้นหลายรายการ
โปรแกรมเมอร์เกลียดการทำซ้ำรหัส พวกเขายังคิดหลักการพัฒนาที่สอดคล้องกัน — DRY : Don't Repeat Yourself แต่เมื่อจัดการกับข้อยกเว้น มีโอกาสบ่อยครั้งที่try
บล็อกหลายบล็อกตามcatch
ด้วยรหัสเดียวกัน
หรืออาจมี 3 catch
บล็อกที่มีรหัสเดียวกัน และอีก 2 catch
บล็อกที่มีรหัสเหมือนกัน นี่เป็นสถานการณ์มาตรฐานเมื่อโครงการของคุณจัดการกับข้อยกเว้นอย่างมีความรับผิดชอบ
เริ่มต้นด้วยเวอร์ชัน 7 ในภาษา Java เพิ่มความสามารถในการระบุข้อยกเว้นหลายประเภทในcatch
บล็อก เดียว มีลักษณะประมาณนี้:
try
{
// Code where an exception might occur
}
catch (ExceptionType1 | ExceptionType2 | ExceptionType3 name)
{
// Exception handling code
}
คุณสามารถมีบล็อกได้มากเท่าcatch
ที่คุณต้องการ อย่างไรก็ตามcatch
บล็อกเดียวไม่สามารถระบุข้อยกเว้นที่สืบทอดกันได้ กล่าวอีกนัยหนึ่ง คุณไม่สามารถเขียน catch ( Exception
| RuntimeException
e) ได้ เนื่องจากRuntimeException
คลาสสืบทอดException
มา
GO TO FULL VERSION