การทำความเข้าใจกับข้อยกเว้นที่ทำเครื่องหมายกับการตรวจสอบใน Java


703

Joshua Bloch ใน " Effective Java " กล่าวว่า

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

ลองดูว่าฉันเข้าใจสิ่งนี้ถูกต้องหรือไม่

นี่คือความเข้าใจของฉันเกี่ยวกับข้อยกเว้นที่ตรวจสอบ:

try{
    String userInput = //read in user input
    Long id = Long.parseLong(userInput);
}catch(NumberFormatException e){
    id = 0; //recover the situation by setting the id to 0
}

1. ข้างต้นถือว่าเป็นข้อยกเว้นที่ตรวจสอบหรือไม่

2. RuntimeException เป็นข้อยกเว้นที่ไม่ได้ตรวจสอบหรือไม่?

นี่คือความเข้าใจของฉันเกี่ยวกับข้อยกเว้นที่ไม่ได้ตรวจสอบ:

try{
    File file = new File("my/file/path");
    FileInputStream fis = new FileInputStream(file);   
}catch(FileNotFoundException e){

//3. What should I do here?
    //Should I "throw new FileNotFoundException("File not found");"?
    //Should I log?
    //Or should I System.exit(0);?
}

4. ตอนนี้รหัสข้างต้นไม่สามารถเป็นข้อยกเว้นที่ตรวจสอบได้หรือไม่ ฉันสามารถกู้สถานการณ์เช่นนี้ได้หรือไม่? ให้ฉัน? (หมายเหตุ: คำถามที่ 3 ของฉันอยู่ด้านcatchบน)

try{
    String filePath = //read in from user input file path
    File file = new File(filePath);
    FileInputStream fis = new FileInputStream(file);   
}catch(FileNotFoundException e){
    //Kindly prompt the user an error message
    //Somehow ask the user to re-enter the file path.
}

5. ทำไมผู้คนถึงทำเช่นนี้?

public void someMethod throws Exception{

}

ทำไมพวกเขาปล่อยให้ฟองข้อยกเว้นขึ้นมา? การจัดการข้อผิดพลาดนั้นเร็วขึ้นหรือไม่ ทำไมฟองขึ้น?

6. ฉันควรทำให้มีข้อยกเว้นที่แน่นอนหรือปิดบังโดยใช้ข้อยกเว้น

ข้างล่างนี้คือการอ่านของฉัน

ใน Java ฉันควรสร้างข้อยกเว้นที่ตรวจสอบเมื่อใดและเมื่อใดควรเป็นข้อยกเว้นรันไทม์

จะเลือกข้อยกเว้นที่ทำเครื่องหมายและไม่เลือกได้เมื่อใด


6
ฉันมีตัวอย่างที่ยอดเยี่ยมของข้อยกเว้นที่ไม่ได้ตรวจสอบ ฉันมีDataSeriesคลาสที่เก็บข้อมูลซึ่งจะต้องอยู่ในลำดับตามเวลาเสมอ มีวิธีการที่จะเพิ่มใหม่คือการสิ้นสุดของการDataPoint DataSeriesหากรหัสของฉันทั้งหมดทำงานอย่างถูกต้องตลอดทั้งโครงการ a DataPointไม่ควรถูกเพิ่มไปยังจุดสิ้นสุดซึ่งมีวันที่ก่อนหน้าไปยังรหัสที่มีอยู่แล้วในตอนท้าย โมดูลทั้งหมดในโครงการทั้งหมดถูกสร้างขึ้นด้วยความจริงแท้นี้ อย่างไรก็ตามฉันจะตรวจสอบเงื่อนไขนี้และโยนข้อยกเว้นที่ไม่ได้ตรวจสอบหากเกิดขึ้น ทำไม? ถ้ามันเกิดขึ้นฉันต้องการรู้ว่าใครกำลังทำสิ่งนี้อยู่และแก้ไขมัน
Erick Robertson

3
เพื่อเพิ่มความสับสนมากยิ่งขึ้น หลายคนเรียกร้องให้มีการตรวจสอบข้อยกเว้น ~ 10 ปีก่อน แต่มุมมองทุกวันนี้มีมากขึ้นเรื่อย ๆ (แต่ฉันไม่เห็นด้วยกับเรื่องนี้)
Kaj

10
มันจะมีประโยชน์ในการจัดการข้อยกเว้นเมื่อคุณมีสิ่งที่มีประโยชน์ที่จะทำมันมิฉะนั้นคุณควรปล่อยให้ผู้โทรจัดการมัน การบันทึกและการแกล้งทำไม่เกิดขึ้นมักจะไม่มีประโยชน์ เพียงแค่โยนอีกครั้งมันไม่มีจุดหมาย การห่อข้อมูลใน RuntimeException นั้นไม่มีประโยชน์อย่างที่คิดบางอย่างมันแค่ทำให้คอมไพเลอร์หยุดช่วยคุณ (IMHO)
Peter Lawrey

40
เราควรหยุดใช้ข้อกำหนดที่ทำให้เข้าใจผิดอย่างกว้างขวางของข้อยกเว้นที่ถูกตรวจสอบ / ไม่ถูกตรวจสอบ พวกเขาควรจะเรียกว่าเช็คอินได้รับคำสั่ง VS เช็คอินไม่ได้รับคำสั่งข้อยกเว้น
ความสุข Geek

3
ฉันเคยคิดเช่นกันว่าจุดที่ 5 เป็นโมฆะสาธารณะ method_name พ่นข้อยกเว้น {} ทำไมบางคนทำเช่นนั้น?
Maveňツ

คำตอบ:


475

หลายคนบอกว่าไม่ควรใช้ข้อยกเว้นที่ตรวจสอบ (เช่นสิ่งเหล่านี้ที่คุณควรตรวจจับหรือทำใหม่) พวกเขาถูกกำจัดใน C # และภาษาส่วนใหญ่ไม่มี ดังนั้นคุณสามารถส่งคลาสย่อยของRuntimeException(ข้อยกเว้นที่ไม่ได้ตรวจสอบ) ได้เสมอ

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

นี่คือมุมมองของฉันขยายในหัวข้อ

สำหรับคำถามเฉพาะ:

  1. คือNumberFormatExceptionพิจารณายกเว้นการตรวจสอบ?
    ไม่มีการNumberFormatExceptionตรวจสอบ (= คือ subclass ของRuntimeException) ทำไม? ฉันไม่รู้ (แต่ควรมีวิธีการisValidInteger(..))

  2. เป็นRuntimeExceptionข้อยกเว้นไม่ถูกตรวจสอบ?
    ใช่แล้ว

  3. ฉันควรทำอะไรที่นี่
    ขึ้นอยู่กับรหัสนี้และสิ่งที่คุณต้องการให้เกิดขึ้น ถ้ามันอยู่ในเลเยอร์ UI - จับมันและแสดงคำเตือน; ถ้าอยู่ในชั้นบริการ - อย่าจับเลย - ปล่อยให้มันฟอง อย่ากลืนข้อยกเว้น หากมีข้อยกเว้นเกิดขึ้นในกรณีส่วนใหญ่คุณควรเลือกข้อใดข้อหนึ่งต่อไปนี้:

    • เข้าสู่ระบบและกลับมา
    • สร้างใหม่อีกครั้ง (ประกาศว่าจะโยนโดยวิธีการ)
    • สร้างข้อยกเว้นใหม่โดยส่งผ่านตัวสร้างปัจจุบันในตัวสร้าง
  4. ตอนนี้รหัสข้างต้นไม่สามารถเป็นข้อยกเว้นที่ตรวจสอบได้หรือไม่ ฉันสามารถพยายามกู้คืนสถานการณ์เช่นนี้ได้หรือไม่ ให้ฉัน?
    มันน่าจะเป็นไปได้ แต่ไม่มีอะไรหยุดคุณจากการตรวจจับข้อยกเว้นที่ไม่ได้ตรวจสอบเช่นกัน

  5. เหตุใดผู้คนจึงเพิ่มชั้นเรียนExceptionในประโยคข้อผิดพลาด?
    ส่วนใหญ่มักจะเป็นเพราะคนขี้เกียจที่จะพิจารณาสิ่งที่จะจับและสิ่งที่จะพลิก การขว้างปาExceptionเป็นวิธีปฏิบัติที่ไม่ดีและควรหลีกเลี่ยง

อนิจจาไม่มีกฎเดียวที่ให้คุณพิจารณาว่าเมื่อใดที่จะต้องจับอีกครั้งเมื่อใดควรใช้การตรวจสอบและเมื่อใดที่จะใช้ข้อยกเว้นที่ไม่ได้ตรวจสอบ ฉันยอมรับว่าสิ่งนี้ทำให้เกิดความสับสนและรหัสไม่ดีจำนวนมาก หลักการทั่วไประบุไว้โดย Bloch (คุณอ้างถึงส่วนหนึ่งของมัน) และหลักการทั่วไปคือการรื้อฟื้นข้อยกเว้นไปยังชั้นที่คุณสามารถจัดการได้


36
เกี่ยวกับการโยนข้อยกเว้นไม่ได้เป็นเพราะคนขี้เกียจมันก็เป็นเรื่องธรรมดาที่คุณเมื่อคุณใช้เฟรมเวิร์กให้ผู้ใช้เฟรมเวิร์กสามารถโยนข้อยกเว้นใด ๆ คุณสามารถตรวจสอบลายเซ็นของส่วนต่อประสานที่สามารถโทรได้ใน JSE
Kaj

10
@Kaj - ใช่สิ่งทั่วไปเช่น Callable, interceptors และชอบเป็นกรณีพิเศษ แต่ในกรณีส่วนใหญ่ก็เพราะคนขี้เกียจ :)
Bozho

7
เรื่อง: 3.1 "เข้าสู่ระบบและกลับมา" ทำอย่างรอบคอบ ใกล้กับการกินหรือซ่อนและข้อยกเว้น ฉันจะทำสิ่งนี้เพื่อสิ่งที่ไม่ได้บ่งบอกถึงปัญหานั่นไม่ได้ยอดเยี่ยมจริงๆ บันทึกถูกน้ำท่วมและไม่สนใจง่ายเกินไป
Chris

4
"เมื่อคุณต้องการบังคับให้ผู้ใช้ API ของคุณคิดว่าจะจัดการกับสถานการณ์พิเศษอย่างไร" - คุณไม่สามารถบังคับให้ใครคิดถ้าพวกเขาไม่ต้องการ หากพวกเขาไม่ต้องการคิดพวกเขาจะเขียนบล็อกข้อยกเว้นที่น่าสงสารซึ่งไม่ได้ทำอะไรเลยหรือแย่กว่านั้นคือลบหรือแทรกแซงด้วยข้อมูลข้อผิดพลาดที่สำคัญ นั่นคือเหตุผลที่ข้อยกเว้นที่ตรวจสอบมีความล้มเหลว
adrianos

3
@adrianos "... คุณไม่สามารถบังคับใครให้คิดได้ถ้าพวกเขาไม่ต้องการ .... " ด้วยความคิดนี้เราสามารถลบข้อผิดพลาดในการคอมไพล์ ... ฉันไม่ได้กำหนดเป้าหมายคุณจริงๆฉันได้ยินสิ่งนี้ เวลาโต้แย้งและอีกครั้งและยังพบว่ามันเป็นคำอธิบายที่แย่ที่สุดที่เป็นไปได้สำหรับการติดฉลากข้อยกเว้น Checked ว่าเป็นความล้มเหลว ในฐานะที่เป็นบันทึกด้านข้างฉันได้เห็นมาก่อนภาษาที่คอมไพล์ (และข้อผิดพลาด runtime เช่นกัน) ได้ทำอย่างมีประสิทธิภาพเป็นไปไม่ได้โดย desing ถนนสายนั้นนำไปสู่สถานที่มืดมน
Newtopian

233

ไม่ว่าจะเป็นสิ่งที่ "ตรวจสอบข้อยกเว้น" ไม่มีอะไรเกี่ยวข้องกับว่าคุณจับมันหรือสิ่งที่คุณทำในการบล็อก catch มันเป็นคุณสมบัติของคลาสยกเว้น สิ่งใดที่เป็น subclass ของException ยกเว้นสำหรับRuntimeExceptionและ subclasses ที่เป็นข้อยกเว้นการตรวจสอบ

คอมไพเลอร์ Java บังคับให้คุณตรวจจับข้อยกเว้นที่เลือกหรือประกาศในลายเซ็นเมธอด มันควรจะปรับปรุงความปลอดภัยของโปรแกรม แต่ความเห็นส่วนใหญ่ดูเหมือนว่ามันไม่คุ้มกับปัญหาการออกแบบที่สร้างขึ้น

ทำไมพวกเขาปล่อยให้ฟองข้อยกเว้นขึ้นมา? ไม่จัดการข้อผิดพลาดเร็วกว่าดีกว่า ทำไมฟองขึ้น?

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


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

12
"สิ่งใดก็ตามที่เป็นคลาสย่อยของ Throwable ยกเว้นสำหรับ RuntimeException และคลาสย่อยนั้นเป็นข้อยกเว้นที่เลือก" - ข้อความของคุณไม่ถูกต้อง ข้อผิดพลาดยังสืบทอด Throwable และจะไม่ถูกตรวจสอบ
Bartzilla

8
@ JonasEicher: โดยทั่วไปประโยชน์หลักของข้อยกเว้นคือพวกเขาอนุญาตให้คุณเลือกตำแหน่งที่คุณต้องการจัดการข้อผิดพลาดซึ่งมักจะค่อนข้างสูงในขณะที่รักษาเลเยอร์ระหว่างปราศจากข้อผิดพลาดในการจัดการสิ่งประดิษฐ์ การตรวจสอบข้อยกเว้นทำลายข้อได้เปรียบนั้นอย่างแน่นอน ปัญหาอีกข้อหนึ่งคือความแตกต่างที่ตรวจสอบ / ไม่ถูกตรวจสอบนั้นเชื่อมโยงกับคลาสข้อยกเว้นซึ่งแสดงถึงการจัดหมวดหมู่แนวคิดของข้อยกเว้น - การผสมสองด้านที่ไม่เกี่ยวข้องกันเลย
Michael Borgwardt

2
"แต่ความเห็นส่วนใหญ่ดูเหมือนว่าจะไม่คุ้มกับปัญหาการออกแบบที่สร้างขึ้น" - การอ้างอิงโปรด?
kervin

3
@Bartzilla ใช่ เพื่อความสมบูรณ์ขณะที่ javadoc Throwableพูดว่า: "Throwable และคลาสย่อยใด ๆ ของ Throwable ที่ไม่ได้เป็นคลาสย่อยของ RuntimeException หรือข้อผิดพลาดใด ๆ ถือเป็นข้อยกเว้นที่ตรวจสอบแล้ว"
Bart van Heukelom

74
  1. ข้างต้นถือว่าเป็นข้อยกเว้นที่ตรวจสอบหรือไม่ ไม่มีความจริงที่ว่าคุณมีการจัดการข้อยกเว้นไม่ได้ทำให้มันถ้ามันเป็นChecked ExceptionRuntimeException

  2. คือ? ใช่RuntimeExceptionunchecked exception

Checked Exceptionsเป็นsubclassesของjava.lang.Exception Unchecked Exceptionsที่มีsubclassesของjava.lang.RuntimeException

การโทรจากการโยนข้อยกเว้นที่เลือกจะต้องอยู่ในบล็อค try {} หรือจัดการในระดับที่สูงกว่าในตัวเรียกของเมธอด ในกรณีนั้นวิธีการปัจจุบันจะต้องประกาศว่ามันจะโยนข้อยกเว้นดังกล่าวเพื่อให้ผู้โทรสามารถจัดการที่เหมาะสมในการจัดการข้อยกเว้น

หวังว่านี่จะช่วยได้

ถาม: ฉันควรทำให้มีข้อยกเว้นที่แน่นอนหรือปิดบังโดยใช้ข้อยกเว้นหรือไม่

ตอบ: ใช่นี่เป็นคำถามที่ดีมากและการพิจารณาการออกแบบที่สำคัญ ข้อยกเว้นคลาสเป็นคลาสข้อยกเว้นทั่วไปมากและสามารถใช้เพื่อตัดข้อยกเว้นระดับต่ำภายใน คุณควรสร้างข้อยกเว้นที่กำหนดเองและห่อไว้ข้างใน แต่สิ่งที่ยิ่งใหญ่ - ไม่เคยคลุมเครือในต้นเหตุดั้งเดิม สำหรับอดีตให้Don't everทำตาม -

try {
     attemptLogin(userCredentials);
} catch (SQLException sqle) {
     throw new LoginFailureException("Cannot login!!"); //<-- Eat away original root cause, thus obscuring underlying problem.
}

ให้ทำดังนี้

try {
     attemptLogin(userCredentials);
} catch (SQLException sqle) {
     throw new LoginFailureException(sqle); //<-- Wrap original exception to pass on root cause upstairs!.
}

การกินสาเหตุที่แท้จริงออกไปฝังอยู่สาเหตุที่แท้จริงนอกเหนือการกู้คืนเป็นฝันร้ายสำหรับทีมสนับสนุนการผลิตซึ่งทั้งหมดที่พวกเขาได้รับการเข้าถึงคือบันทึกแอปพลิเคชันและข้อความแสดงข้อผิดพลาด แม้ว่าหลังจะเป็นการออกแบบที่ดีกว่า แต่หลาย ๆ คนไม่ได้ใช้บ่อยนักเพราะนักพัฒนาซอฟต์แวร์ไม่สามารถส่งต่อข้อความพื้นฐานไปยังผู้โทรได้ ดังนั้นโปรดจดบันทึกไว้: Always pass on the actual exceptionย้อนกลับไม่ว่าจะมีข้อยกเว้นเฉพาะแอปพลิเคชันหรือไม่

เมื่อลองจับ RuntimeExceptions

RuntimeExceptionตามกฎทั่วไปไม่ควรลองจับ พวกเขามักส่งสัญญาณข้อผิดพลาดในการเขียนโปรแกรมและควรจะอยู่คนเดียว RuntimeExceptionแต่โปรแกรมเมอร์ควรตรวจสอบเงื่อนไขข้อผิดพลาดก่อนที่จะอัญเชิญรหัสบางอย่างที่อาจจะส่งผลในการ ตัวอย่างเช่น:

try {
    setStatusMessage("Hello Mr. " + userObject.getName() + ", Welcome to my site!);
} catch (NullPointerException npe) {
   sendError("Sorry, your userObject was null. Please contact customer care.");
}

นี่คือการฝึกเขียนโปรแกรมที่ไม่ดี แทนที่จะตรวจสอบเป็นโมฆะควรได้รับการทำเช่น -

if (userObject != null) {
    setStatusMessage("Hello Mr. " + userObject.getName() + ", Welome to my site!);
} else {
   sendError("Sorry, your userObject was null. Please contact customer care.");
}

แต่มีบางครั้งที่การตรวจสอบข้อผิดพลาดดังกล่าวมีราคาแพงเช่นการจัดรูปแบบตัวเลขให้พิจารณาสิ่งนี้ -

try {
    String userAge = (String)request.getParameter("age");
    userObject.setAge(Integer.parseInt(strUserAge));
} catch (NumberFormatException npe) {
   sendError("Sorry, Age is supposed to be an Integer. Please try again.");
}

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

ดังนั้นNullPointerExceptionและNumberFormatExceptionทั้งคู่การRuntimeExceptionsจับ a NullPointerExceptionควรแทนที่ด้วยการตรวจสอบ null อย่างสง่างามในขณะที่ฉันแนะนำให้จับNumberFormatExceptionอย่างชัดเจนเพื่อหลีกเลี่ยงการแนะนำโค้ดที่เป็นไปได้ของข้อผิดพลาดที่เป็นไปได้


ขอบคุณ. อีกหนึ่งคำถามเมื่อคุณเดือดปุด ๆ ขึ้นฉันควรฟองขึ้นยกเว้นแน่นอนหรือหน้ากากโดยใช้exception Exceptionฉันเขียนโค้ดที่ด้านบนของรหัสดั้งเดิมและExceptionถูกอัดแน่นไปทั่วสถานที่ ฉันสงสัยว่านี่เป็นพฤติกรรมที่ถูกต้องหรือไม่?
Thang Pham

1
นี่เป็นคำถามที่ดีและสำคัญแก้ไขคำตอบของฉันเพื่อรวมคำอธิบาย
d-live

ขอบคุณมาก. มันจะเป็นไปได้สำหรับคุณที่จะแสดงเนื้อหาของLoginFailureException(sqle)?
Thang Pham

1
ฉันไม่มีรหัสใด ๆ สำหรับสิ่งนั้นฉันเพิ่งปรุงชื่อเป็นต้นถ้าคุณเห็น java.lang.Exception มี 4 ตัวสร้างสองตัวยอมรับ java.lang.rowable ในตัวอย่างด้านบนฉันสันนิษฐานว่าLoginFailureExceptionขยายExceptionและประกาศตัวสร้างpublic LoginFailureException(Throwable cause) { super(cause) }
d-live

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

19

1. หากคุณไม่แน่ใจเกี่ยวกับข้อยกเว้นให้ตรวจสอบ API:

 java.lang.Object
 extended by java.lang.Throwable
  extended by java.lang.Exception
   extended by java.lang.RuntimeException  //<-NumberFormatException is a RuntimeException  
    extended by java.lang.IllegalArgumentException
     extended by java.lang.NumberFormatException

2. ใช่และทุกข้อยกเว้นที่ขยายออกไป

3. ไม่จำเป็นต้องจับและโยนข้อยกเว้นเดียวกัน คุณสามารถแสดงกล่องโต้ตอบไฟล์ใหม่ในกรณีนี้

4. FileNotFoundExceptionคือข้อยกเว้นที่ตรวจสอบแล้ว

5. หากคาดว่าวิธีการโทรsomeMethodเพื่อตรวจสอบข้อยกเว้นสามารถโยนทิ้งได้ มันแค่ "ส่งบอล" ตัวอย่างของการใช้มันคือถ้าคุณต้องการที่จะโยนมันในวิธีการส่วนตัวของคุณเองและจัดการข้อยกเว้นในวิธีการสาธารณะของคุณแทน

การอ่านที่ดีคือเอกสารของ Oracle เอง: http://download.oracle.com/javase/tutorial/essential/exceptions/runtime.html

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

คำถามต่อไปอาจเป็น: "ถ้าเป็นเรื่องที่ดีที่จะจัดทำเอกสาร API ของวิธีการรวมถึงข้อยกเว้นที่สามารถใช้งานได้ ข้อยกเว้นรันไทม์แสดงถึงปัญหาที่เป็นผลมาจากปัญหาการเขียนโปรแกรมและดังนั้นรหัสลูกค้า API ไม่สามารถคาดว่าจะกู้คืนได้จากพวกเขาหรือเพื่อจัดการกับพวกเขาในทางใดทางหนึ่ง ปัญหาดังกล่าวรวมถึงข้อยกเว้นทางคณิตศาสตร์เช่นการหารด้วยศูนย์ ข้อยกเว้นของตัวชี้เช่นพยายามเข้าถึงวัตถุผ่านการอ้างอิงแบบ null และข้อยกเว้นการจัดทำดัชนีเช่นการพยายามเข้าถึงองค์ประกอบอาร์เรย์ผ่านดัชนีที่มีขนาดใหญ่เกินไปหรือเล็กเกินไป

นอกจากนี้ยังมีข้อมูลสำคัญในJava Language Specification :

ตรวจสอบการเรียนยกเว้นมีชื่ออยู่ในพ่นประโยคเป็นส่วนหนึ่งของสัญญาระหว่าง implementor และผู้ใช้วิธีการหรือนวกรรมิก

บรรทัดล่างคือ IMHO ที่คุณสามารถตรวจจับได้RuntimeExceptionแต่คุณไม่จำเป็นต้องใช้และในความเป็นจริงการดำเนินการไม่จำเป็นต้องรักษาข้อยกเว้นที่ไม่ได้ตรวจสอบเหมือนกันซึ่งเกิดขึ้นเนื่องจากไม่ได้เป็นส่วนหนึ่งของสัญญา


ขอบคุณ. อีกหนึ่งคำถามเมื่อคุณเดือดปุด ๆ ขึ้นฉันควรฟองขึ้นยกเว้นแน่นอนหรือหน้ากากโดยใช้exception Exceptionฉันเขียนโค้ดด้านบนของรหัสดั้งเดิมบางส่วนและExceptionถูกอัดแน่นไปทั่วสถานที่ ฉันสงสัยว่านี่เป็นพฤติกรรมที่ถูกต้องหรือไม่?
Thang Pham

1
@Harry ฉันจะให้คนที่มีความรู้มากกว่าที่ฉันจะตอบว่า: stackoverflow.com/questions/409563//
Aleadam

10

1) ไม่ NumberFormatException เป็นข้อยกเว้นที่ไม่ได้ตรวจสอบ แม้ว่าคุณจะถูกจับได้ (คุณไม่จำเป็น) เพราะมันไม่ได้ถูกตรวจสอบ นี่เป็นเพราะมันเป็น subclass IllegalArgumentExceptionซึ่งเป็น subclass ของRuntimeExceptionของ

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

3/4) คุณสามารถเตือนผู้ใช้ว่าพวกเขาเลือกไฟล์ที่ไม่มีอยู่และขอไฟล์ใหม่ หรือเพียงแค่ออกจากการแจ้งผู้ใช้ว่าพวกเขาป้อนสิ่งที่ไม่ถูกต้อง

5) การขว้างและจับ'Exception'เป็นวิธีปฏิบัติที่ไม่ดี แต่โดยทั่วไปคุณอาจโยนข้อยกเว้นอื่น ๆ เพื่อให้ผู้โทรสามารถตัดสินใจได้ว่าจะจัดการกับมันอย่างไร ตัวอย่างเช่นถ้าคุณเขียนไลบรารีเพื่อจัดการการอ่านอินพุตไฟล์บางส่วนและวิธีการของคุณผ่านไฟล์ที่ไม่มีอยู่คุณไม่ทราบวิธีจัดการกับไฟล์นั้น ผู้โทรต้องการถามอีกครั้งหรือเลิก? ดังนั้นคุณจะโยนข้อยกเว้นขึ้นโซ่กลับไปที่ผู้โทร

ในหลายกรณีunchecked Exceptionเกิดขึ้นเนื่องจากโปรแกรมเมอร์ไม่ได้ตรวจสอบอินพุต (ในกรณีของNumberFormatExceptionคำถามแรกของคุณ) นั่นเป็นเหตุผลว่าทำไมจึงเป็นตัวเลือกในการจับพวกเขาเนื่องจากมีวิธีการที่สง่างามกว่า


ขอบคุณ. อีกหนึ่งคำถามเมื่อคุณเดือดปุด ๆ ขึ้นฉันควรฟองขึ้นยกเว้นแน่นอนหรือหน้ากากโดยใช้exception Exceptionฉันเขียนโค้ดด้านบนของรหัสดั้งเดิมบางส่วนและExceptionถูกอัดแน่นไปทั่วสถานที่ ฉันสงสัยว่านี่เป็นพฤติกรรมที่ถูกต้องหรือไม่?
Thang Pham

คุณสามารถมีเพียงวิธีการของคุณยังโยนข้อยกเว้น (ซึ่งไม่เหมาะ) หรือจับข้อยกเว้นแล้วโยนข้อยกเว้นที่ดีกว่า (เช่น IOException หรือบางอย่าง) ข้อยกเว้นทั้งหมดสามารถใช้ข้อยกเว้นในตัวสร้างของพวกเขาเป็น 'สาเหตุ' ดังนั้นคุณควรใช้มัน
dontocsata

8

ตรวจสอบ - มีแนวโน้มที่จะเกิดขึ้น ตรวจสอบในเวลารวบรวม

เช่น .. FileOperations

ไม่ถูกตรวจสอบ - เนื่องจากข้อมูลไม่ถูกต้อง ตรวจสอบในเวลาทำงาน

เช่น..

String s = "abc";
Object o = s;
Integer i = (Integer) o;

Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
    at Sample.main(Sample.java:9)

ข้อยกเว้นนี้เกิดจากข้อมูลที่ไม่ถูกต้องและไม่สามารถระบุได้ในช่วงเวลารวบรวม


6

ข้อยกเว้นที่ตรวจสอบถูกตรวจสอบในเวลารวบรวมโดย JVM และเกี่ยวข้องกับทรัพยากร (ไฟล์ / db / stream / socket ฯลฯ ) แรงจูงใจของข้อยกเว้นที่ตรวจสอบคือในเวลารวบรวมหากทรัพยากรไม่พร้อมใช้งานแอปพลิเคชันควรกำหนดลักษณะการทำงานทางเลือกเพื่อจัดการกับสิ่งนี้ในบล็อก catch / สุดท้าย

ข้อยกเว้นที่ไม่ได้ตรวจสอบคือข้อผิดพลาดทางโปรแกรมล้วนๆการคำนวณที่ผิดข้อมูลที่เป็นโมฆะหรือแม้แต่ความล้มเหลวในตรรกะทางธุรกิจสามารถนำไปสู่ข้อยกเว้นแบบรันไทม์ มันเป็นเรื่องที่ดีในการจัดการ / จับข้อยกเว้นที่ไม่ได้ตรวจสอบในรหัส

คำอธิบายนำมาจากhttp://coder2design.com/java-interview-questions/


5

คำอธิบายที่ชื่นชอบโดยสิ้นเชิงของฉันเกี่ยวกับความแตกต่างระหว่างข้อยกเว้นที่ไม่ได้ตรวจสอบและการตรวจสอบมีให้โดยบทความเส้นทางการสอนของ Java, " ข้อยกเว้นที่ไม่ได้ตรวจสอบ - การโต้เถียง " (ขออภัยที่ได้รับข้อมูลเบื้องต้นทั้งหมดในโพสต์นี้

นี่คือหลักเกณฑ์ด้านล่าง: หากลูกค้าคาดว่าจะสามารถกู้คืนได้อย่างมีเหตุผลจากข้อยกเว้นให้เป็นข้อยกเว้นที่ตรวจสอบ หากลูกค้าไม่สามารถทำการกู้คืนจากข้อยกเว้นได้ให้ทำให้เป็นข้อยกเว้นที่ไม่ได้ตรวจสอบ

หัวใจของ "สิ่งที่ประเภทของข้อยกเว้นที่จะโยน" คือความหมาย (ในระดับหนึ่ง) และคำพูดข้างต้นให้และแนวทางที่ยอดเยี่ยม (ดังนั้นฉันยังคงปลิวไปตามความคิดที่ C # กำจัดข้อยกเว้นที่ตรวจสอบ - โดยเฉพาะอย่างยิ่ง Liskov ประโยชน์ของพวกเขา)

ส่วนที่เหลือจะเป็นตรรกะ: คอมไพเลอร์ใดที่ฉันคาดหวังว่าจะตอบสนองอย่างชัดเจน? สิ่งที่คุณคาดหวังให้ลูกค้ากู้คืน


5

ในการตอบคำถามสุดท้าย (คนอื่นดูเหมือนจะตอบอย่างละเอียดด้านบน) "ฉันควรจะทำให้ข้อยกเว้นที่แน่นอนหรือปกปิดโดยใช้ข้อยกเว้น"

ฉันสมมติว่าคุณหมายถึงสิ่งนี้:

public void myMethod() throws Exception {
    // ... something that throws FileNotFoundException ...
}

ไม่ประกาศข้อยกเว้นที่แม่นยำที่สุดเท่าที่จะเป็นไปได้เสมอหรือรายการดังกล่าว ข้อยกเว้นที่คุณประกาศวิธีการที่มีความสามารถในการขว้างปาเป็นส่วนหนึ่งของสัญญาระหว่างวิธีการของคุณและผู้โทร การขว้างปา"FileNotFoundException"หมายความว่าเป็นไปได้ว่าชื่อไฟล์ไม่ถูกต้องและจะไม่พบไฟล์นั้น ผู้โทรจะต้องจัดการอย่างชาญฉลาด การขว้างปาExceptionหมายถึง "เฮ้ sh * t เกิดขึ้นได้เลย" ซึ่งเป็นคนจนมาก ๆAPI

ในความคิดเห็นในบทความแรกมีตัวอย่างบางส่วนที่ "พ่นException" เป็นคำประกาศที่ถูกต้องและสมเหตุสมผล แต่นั่นไม่ใช่กรณีของnormalรหัสส่วนใหญ่ที่คุณจะเขียน


ให้ทำข้อยกเว้นการตรวจสอบข้อยกเว้นของคุณเป็นส่วนหนึ่งของเอกสารรหัสของคุณรวมถึงช่วยเหลือบุคคลที่ใช้ซอฟต์แวร์ของคุณ
Salvador Valencia Valencia

5

ข้อยกเว้นรันไทม์ : ข้อยกเว้นรันไทม์อ้างถึงเป็นข้อยกเว้นที่ไม่ได้ตรวจสอบ ข้อยกเว้นอื่น ๆ ทั้งหมดได้รับการตรวจสอบข้อยกเว้นและไม่ได้มาจาก java.lang.RuntimeException

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

มีวิธีการมากมายใน Java API ที่มีการตรวจสอบข้อยกเว้นดังนั้นคุณมักจะเขียนตัวจัดการข้อยกเว้นเพื่อรับมือกับข้อยกเว้นที่สร้างขึ้นโดยวิธีที่คุณไม่ได้เขียน


3

ทำไมพวกเขาปล่อยให้ฟองข้อยกเว้นขึ้นมา? การจัดการข้อผิดพลาดนั้นเร็วขึ้นหรือไม่ ทำไมฟองขึ้น?

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

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


จุดดี. ความหมายคือการทำให้เป็นชั้นที่มีความรับผิดชอบสูงสุดซึ่งควบคุมการไหลของตรรกะและดูแลตรรกะทางธุรกิจสำหรับแอปพลิเคชัน มันจะเป็นไปไม่ได้เช่นสำหรับเลเยอร์ฐานข้อมูลเพื่อสื่อสารกับลูกค้าว่ามีบางสิ่งที่สำคัญขาดหายไปหรือไม่ตอบสนอง เมื่อฟองสบู่ขึ้นไปที่เลเยอร์เซิร์ฟเวอร์ส่วนใหญ่แล้วมันจะส่งต่อไปยังรีเฟรชมุมมองของลูกค้าพร้อมกับข้อความแสดงข้อผิดพลาดร้ายแรง
Salvador Valencia Valencia

3

ฉันคิดว่าการยกเว้นที่ผ่านการตรวจสอบแล้วเป็นสิ่งเตือนใจที่ดีสำหรับนักพัฒนาที่ใช้ไลบรารีภายนอกที่อาจเกิดความผิดพลาดกับโค้ดจากไลบรารีดังกล่าวในสถานการณ์พิเศษ

อ่านเพิ่มเติมเกี่ยวกับข้อยกเว้นที่ไม่ได้ตรวจสอบและตรวจสอบได้ที่นี่http://learnjava.today/2015/11/checked-vs-unchecked-exceptions/


3

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

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

ให้ฉันแสดงตัวอย่างให้คุณดู

มามีส่วนต่อประสานที่ดีและสะอาดดีเช่นนี้

public interface IFoo {
    public void foo();
}

ตอนนี้เราสามารถเขียนวิธีการใช้งานหลายfoo()อย่างเช่นนี้

public class Foo implements IFoo {
    @Override
    public void foo() {
        System.out.println("I don't throw and exception");
    }
}

Class Foo นั้นดีมาก ตอนนี้เรามาลองที่ class Bar กันก่อน

public class Bar implements IFoo {
    @Override
    public void foo() {
        //I'm using InterruptedExcepton because you probably heard about it somewhere. It's a checked exception. Any checked exception will work the same.
        throw new InterruptedException();
    }
}

บาร์ระดับนี้จะไม่รวบรวม เนื่องจาก InterruptedException เป็นข้อยกเว้นที่ทำเครื่องหมายไว้คุณจะต้องจับมัน (ด้วยวิธีลองจับภายใน foo ()) หรือประกาศว่าคุณกำลังโยนมัน (เพิ่มthrows InterruptedExceptionในลายเซ็นเมธอด) เนื่องจากฉันไม่ต้องการบันทึกข้อยกเว้นนี้ที่นี่ (ฉันต้องการให้เผยแพร่ขึ้นไปเพื่อให้ฉันสามารถจัดการกับมันได้ที่อื่น), ขอเปลี่ยนลายเซ็น

public class Bar implements IFoo {
    @Override
    public void foo() throws InterruptedException {
        throw new InterruptedException();
    }
}

บาร์คลาสนี้จะไม่คอมไพล์เช่นกัน! เมธอดของ Bar foo () ไม่ได้แทนที่เมธอดของ IFoo foo () เนื่องจากลายเซ็นของพวกเขานั้นแตกต่างกัน ฉันจะลบคำอธิบายประกอบ @Override แต่ฉันต้องการโปรแกรมกับ IFoo อินเตอร์เฟซที่ชอบและต่อมาในการตัดสินใจเกี่ยวกับการดำเนินงานที่ฉันต้องการที่จะใช้เช่นIFoo foo; foo = new Bar();หากวิธีของ Bar foo () ไม่ได้แทนที่วิธีของ IFoo foo เมื่อฉันทำfoo.foo();มันจะไม่เรียกการใช้งาน foo ของ Bar ()

ในการทำให้ Bar ของpublic void foo() throws InterruptedExceptionแทนที่ IFoo public void foo()ฉันต้องเพิ่มthrows InterruptedExceptionลายเซ็นวิธีของ IFoo อย่างไรก็ตามนี่จะทำให้เกิดปัญหากับคลาส Foo ของฉันเนื่องจากเป็นลายเซ็นของวิธี foo () ที่แตกต่างจากลายเซ็นวิธีของ IFoo นอกจากนี้หากฉันเพิ่มthrows InterruptedExceptionวิธีการของ foo foo () ฉันจะได้รับข้อผิดพลาดอื่นที่ระบุว่าวิธีการของ foo foo () ประกาศว่าจะมีการขัดจังหวะด้วยการขัดจังหวะ

อย่างที่คุณเห็น (ถ้าฉันทำได้ดีในการอธิบายเรื่องนี้) ความจริงที่ว่าฉันกำลังโยนข้อยกเว้นที่ถูกตรวจสอบเช่น InterruptedException บังคับให้ฉันต้องผูกอินเทอร์เฟซของฉัน IFoo กับหนึ่งในการใช้งานของมัน การใช้งานอื่น ๆ !

นี่เป็นเหตุผลสำคัญอย่างหนึ่งที่ทำไมข้อยกเว้นที่ตรวจสอบคือ BAD ในหมวก

ทางออกหนึ่งคือการตรวจจับข้อยกเว้นที่ตรวจสอบแล้วห่อในข้อยกเว้นที่ไม่ได้ตรวจสอบ


2
ใช่มันไม่ดีเพราะคุณบอกว่าคุณไม่ต้องการที่จะจับมัน แต่เพื่อป้องกันไม่ให้ส่งผลกระทบต่อลายเซ็นของ IFOO คุณจะต้อง ฉันต้องการทำเช่นนั้นและดำเนินการแทนการปรับสมดุลอินเทอร์เฟซทั้งหมดของฉันใหม่เพื่อหลีกเลี่ยงการยกเว้น (เพียงเพราะข้อยกเว้นคือ BAD)
Salvador Valencia Valencia

ใช่ฉันเห็นด้วย ฉันค่อนข้างชัดเจนเกี่ยวกับบางสิ่งบางอย่าง ฉันต้องการข้อยกเว้นเพื่อเผยแพร่ดังนั้นฉันสามารถจัดการกับมันได้ที่อื่น ทางออกหนึ่งคือการตรวจสอบ InterruptedException และส่งข้อยกเว้นที่ไม่ได้ตรวจสอบ เช่นเราหลีกเลี่ยงการตรวจสอบข้อยกเว้นและส่งผ่านข้อยกเว้นที่ไม่มีการตรวจสอบ (แม้ว่าพวกเขาจะใช้งานได้ดีในฐานะเสื้อคลุม)
Blueriver

"สิ่งนี้จะทำให้เกิดปัญหากับคลาส Foo ของฉันเนื่องจากลายเซ็นของเมธอด foo () แตกต่างจากลายเซ็นของวิธี IFoo" ฉันเพิ่งทดสอบความคิดของคุณและเป็นไปได้ที่จะรวบรวมแม้ว่าเราจะเพิ่มthrows InterruptedExceptionลายเซ็นวิธีการของ IFoo โดยไม่ทิ้งอะไรในการนำไปใช้ ดังนั้นมันไม่ได้ทำให้เกิดปัญหาใด ๆ หากในส่วนต่อประสานที่คุณทำทุกวิธีการใช้งานลายเซ็นExceptionก็แค่ให้การใช้งานทางเลือกที่จะโยนหรือไม่โยนข้อยกเว้น (ข้อยกเว้นใด ๆ เช่นExceptionแค็ปซูลข้อยกเว้นทั้งหมด)
Flyout91

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

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

3
  • Java แยกความแตกต่างระหว่างข้อยกเว้นสองประเภท (ทำเครื่องหมาย & ไม่เลือก)
  • Java บังคับใช้ข้อกำหนดการตรวจจับหรือประกาศสำหรับข้อยกเว้นที่ตรวจสอบ
  • ประเภทของข้อยกเว้นกำหนดว่าจะตรวจสอบข้อยกเว้นหรือไม่เลือก
  • ประเภทข้อยกเว้นทั้งหมดที่ตรงหรือทางอ้อมsubclassesของคลาสRuntimeException นั้นเป็นข้อยกเว้นที่ไม่ได้ตรวจสอบ
  • ทุกชั้นเรียนที่ได้รับมรดกจากชั้นเรียนExceptionแต่ไม่ได้รับการพิจารณาให้เป็นRuntimeExceptionchecked exceptions
  • คลาสที่สืบทอดจากคลาสของข้อผิดพลาดถูกพิจารณาว่าไม่ถูกทำเครื่องหมาย
  • checked exceptionตรวจสอบคอมไพเลอร์โทรแต่ละวิธีการและการชะลอตัวของการตรวจสอบว่าวิธีการพ่น
    • ถ้าเป็นเช่นนั้นคอมไพเลอร์มั่นใจว่าข้อยกเว้นถูกจับหรือถูกประกาศในข้อพ่น
  • เพื่อตอบสนองความเป็นส่วนหนึ่งของความต้องการประกาศจับหรือประกาศวิธีการที่สร้างข้อยกเว้นต้องมีประโยคที่มีthrowschecked-exception
  • Exception คลาสถูกกำหนดให้ตรวจสอบเมื่อพวกเขาถูกพิจารณาว่ามีความสำคัญพอที่จะรับหรือประกาศ

2

นี่เป็นกฎง่ายๆที่สามารถช่วยคุณตัดสินใจได้ มันเกี่ยวข้องกับวิธีการใช้อินเตอร์เฟสใน Java

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

ดูวิธีการของอินเตอร์เฟสและพิจารณาข้อยกเว้นที่อาจเกิดขึ้น:

หากมีข้อยกเว้นสามารถโยนโดยวิธีการโดยไม่คำนึงถึงการใช้งานพื้นฐาน (ในคำอื่น ๆ มันอธิบายฟังก์ชั่นเท่านั้น) จากนั้นก็อาจจะเป็นข้อยกเว้นการตรวจสอบในอินเตอร์เฟซ

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

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

โดยปกติแล้วคุณไม่ควรวางแผนที่จะ "ยกเว้นฟองสบู่" (catch และ rethrow) ข้อยกเว้นควรได้รับการจัดการโดยผู้โทร (ในกรณีที่มีการตรวจสอบ) หรือควรดำเนินไปจนถึงตัวจัดการระดับสูง (ในกรณีนี้จะง่ายที่สุดหากไม่ได้เลือก)


2

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


2

กล่าวโดยย่อข้อยกเว้นที่โมดูลหรือโมดูลข้างต้นของคุณควรจัดการในระหว่างรันไทม์เรียกว่าการตรวจสอบข้อยกเว้น คนอื่น ๆ ที่มีข้อยกเว้นไม่ถูกตรวจสอบซึ่งมีทั้งหรือRuntimeExceptionError

ในวิดีโอนี้อธิบายถึงข้อยกเว้นที่ตรวจสอบและไม่ได้ตรวจสอบใน Java:
https://www.youtube.com/watch?v=ue2pOqLaArw


1

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


หนอ ถ้า NumberFormatException เป็นข้อยกเว้นที่ตรวจสอบอย่างที่คุณพูดมันไม่ขัดแย้งกับข้อเท็จจริงที่ว่ามันได้รับมาจาก RuntimeExceptionหรือไม่?
EIS

ขออภัยฉันไม่ชัดเจนมาก ฉันอ้างถึง FileNotFoundException ไม่ใช่ NumberFormatException จาก # 2 & # 4 ของเขาดูเหมือนว่าเขาคิดว่า Checked vs. Unchecked ขึ้นอยู่กับวิธีที่คุณจัดการข้อยกเว้นหลังจากที่จับมัน ไม่ใช่ว่ามันถูกกำหนด
mamboking

-1

หากใครสนใจอีกหลักฐานหนึ่งที่ไม่ชอบข้อยกเว้นที่ตรวจสอบดูวรรคสองสามของห้องสมุด JSON ยอดนิยม:

"แม้ว่านี่จะเป็นข้อยกเว้นที่ตรวจสอบ แต่ก็ไม่สามารถกู้คืนได้ผู้โทรส่วนใหญ่ควรจะตัดข้อยกเว้นนี้ด้วยข้อยกเว้นที่ไม่ได้ตรวจสอบ

ดังนั้นทำไมในโลกที่ทุกคนจะทำให้นักพัฒนาตรวจสอบข้อยกเว้นถ้าเราควร "เพียงแค่ห่อ" แทน? ฮ่า ๆ

http://developer.android.com/reference/org/json/JSONException.html


4
เพราะมันเป็นเพียงผู้โทรส่วนใหญ่ไม่ใช่ผู้โทรทุกคนที่ควรห่อและ rethrow ความจริงที่ว่ามีการตรวจสอบข้อยกเว้นหมายถึงผู้โทรต้องคิดว่าพวกเขาเป็นหนึ่งในผู้โทรที่ "มากที่สุด" หรือเป็นหนึ่งในชนกลุ่มน้อยที่สามารถและควรจัดการกับข้อยกเว้น
Warren Dew

1
หากคุณต้องการตรวจสอบข้อผิดพลาดสำหรับการโทรทุกครั้งที่คุณ "ย้อนกลับ" ถึง C ข้อยกเว้นเป็นวิธีการแยกการทำงานของโปรแกรมปกติออกจากความผิดปกติโดยไม่ทำให้รหัสของคุณสกปรก ข้อยกเว้นทำให้คุณไม่สามารถเพิกเฉยข้อผิดพลาดได้ในระดับหนึ่ง
Slawomir

-1

ตรวจสอบข้อยกเว้น :

  • ข้อยกเว้นที่ตรวจสอบโดยคอมไพเลอร์สำหรับการดำเนินการที่ราบรื่นของโปรแกรมเมื่อรันไทม์เรียกว่า Checked Exception

  • สิ่งเหล่านี้เกิดขึ้นในเวลารวบรวม

  • หากสิ่งเหล่านี้ไม่ได้รับการจัดการอย่างเหมาะสมพวกเขาจะให้ข้อผิดพลาดเวลาในการรวบรวม (Not Exception)
  • คลาสย่อยทั้งหมดของคลาส Exception ยกเว้น RuntimeException คือ Checked Exception

    ตัวอย่างสมมุติ - สมมติว่าคุณกำลังออกจากบ้านเพื่อสอบ แต่ถ้าคุณตรวจสอบว่าคุณนำตั๋วฮอลล์ของคุณที่บ้าน (เวลารวบรวม) จากนั้นจะไม่มีปัญหาใด ๆ ที่ Exam Hall (รันไทม์)

ข้อยกเว้นที่ไม่ได้ตรวจสอบ :

  • ข้อยกเว้นที่ไม่ได้ตรวจสอบโดยคอมไพเลอร์เรียกว่า Unchecked Exceptions

  • สิ่งเหล่านี้เกิดขึ้นที่รันไทม์

  • หากข้อยกเว้นเหล่านี้ไม่ได้รับการจัดการอย่างถูกต้องพวกเขาจะไม่ให้ข้อผิดพลาดเวลารวบรวม แต่โปรแกรมจะถูกยกเลิกก่อนเวลารันไทม์

  • คลาสย่อยทั้งหมดของ RunTimeException และ Error เป็นข้อยกเว้นที่ไม่ได้ทำเครื่องหมายไว้

    ตัวอย่างสมมุติ - สมมติว่าคุณอยู่ในห้องสอบของคุณ แต่อย่างใดโรงเรียนของคุณประสบอุบัติเหตุทางไฟ (หมายถึงเวลาทำงาน) ซึ่งคุณไม่สามารถทำอะไรในเวลานั้น แต่ข้อควรระวังสามารถทำได้ก่อน (รวบรวมเวลา)


-2

ข้อยกเว้นทั้งหมดจะต้องตรวจสอบข้อยกเว้น

  1. ข้อยกเว้นที่ไม่ได้ตรวจสอบเป็นข้อ จำกัด ของ gotos และ gotos ที่ไม่ จำกัด นั้นก็ถือว่าเป็นสิ่งที่ไม่ดี

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

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

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