Java Try Catch สุดท้ายบล็อกโดยไม่จับ


125

ฉันกำลังตรวจสอบโค้ดใหม่ โปรแกรมมีการทดลองและบล็อกสุดท้ายเท่านั้น เนื่องจากบล็อก catch ถูกแยกออกการ try block จะทำงานอย่างไรหากพบข้อยกเว้นหรือสิ่งใดที่สามารถโยนได้ มันไปที่บล็อกสุดท้ายโดยตรงหรือไม่?



25
@mP ทุกคนควรจะตรวจสอบโค้ดและถามคำถามจากพวกเขาคือวิธีเรียนรู้และปรับปรุง
Carl Pritchett

คำตอบ:


130

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

สุดท้ายบล็อกจะถูกดำเนินการเสมอไม่ว่าจะมีข้อยกเว้นหรือไม่ก็ตาม


11
ย่อหน้าแรกไม่จำเป็นต้องเป็นจริง ลองบล็อกสามารถซ้อนกันได้ ข้อยกเว้นใด ๆ ที่ไม่ถูกตรวจจับไม่ได้ตรวจสอบหรือไม่จะฟองออกจากวิธีการ
Andy Thomas

4
ลองบล็อกสามารถซ้อนกันได้ แต่ฉันไม่แนะนำ ฉันไม่เขียนโค้ดด้วยวิธีนั้น
duffymo

2
@duffymo: ความหมายของ "bubbled out of the method" คืออะไร?
58

5
@Anand เป็นภาษาที่ไม่ใช่เทคนิคเล็กน้อยสำหรับ "การยกเว้น"
duffymo

2
ไม่ละเว้น; ส่งผ่านห่วงโซ่วิธีการ
duffymo

93

หมายเหตุเล็ก ๆ ในtry/ finally: สุดท้ายจะดำเนินการเว้นแต่

  • System.exit() ถูกเรียก.
  • JVM ขัดข้อง
  • try{}บล็อกไม่สิ้นสุด (เช่นวงไม่มีที่สิ้นสุด)

4
เกี่ยวกับอะไรtry{..} catch{ throw ..} finally{..}? ฉันคิดว่าในที่สุดจะไม่ถูกประหารชีวิต
sbeliakov

10
ในกรณีนี้จะยังคงถูกเรียกในที่สุด เฉพาะข้อยกเว้นเดิมเท่านั้นที่หายไป
Peter Lawrey

สุดท้ายจะไม่ถูกเรียกใช้งานหากคุณเรียก System.exit () มาก่อน
mmirror

2
@jyw นั่นคือสิ่งที่ฉันหมายถึงรายการแรกในรายการด้านบน
Peter Lawrey

ฉันต้องบอกว่าสิ่งนี้ครอบคลุมทุกฐาน!
Oscar Bravo

39

ข้อกำหนดภาษา Java (1)อธิบายวิธีtry-catch-finallyดำเนินการ การไม่มีการจับจะเท่ากับการไม่มีการจับที่สามารถจับโยนได้

  • หากการดำเนินการของ try block เสร็จสิ้นในทันทีเนื่องจากการโยนค่า V มีทางเลือก:
    • หากประเภทรันไทม์ของ V สามารถกำหนดให้กับพารามิเตอร์ของประโยค catch ของคำสั่ง try ได้ดังนั้น ...
      ...
    • หากประเภทเวลาทำงานของ V ไม่ได้มอบหมายให้กับพารามิเตอร์จับประโยคของคำสั่งลองใด ๆแล้วกลุ่มสุดท้ายจะถูกดำเนินการ จากนั้นมีทางเลือก:
      • หากการบล็อกในที่สุดเสร็จสิ้นตามปกติคำสั่ง try จะเสร็จสิ้นทันทีเนื่องจากการโยนค่า V
      • หากในที่สุดการบล็อกเสร็จสมบูรณ์ในทันทีด้วยเหตุผล S คำสั่ง try จะเสร็จสมบูรณ์ทันทีด้วยเหตุผล S (และการโยนมูลค่า V จะถูกทิ้งและลืมไป)

(1) ดำเนินการลองจับในที่สุด


16

ด้านในจะถูกดำเนินการก่อนที่จะโยนข้อยกเว้นไปยังบล็อกด้านนอก

public class TryCatchFinally {

  public static void main(String[] args) throws Exception {

    try{
        System.out.println('A');
        try{
            System.out.println('B');
            throw new Exception("threw exception in B");
        }
        finally
        {
            System.out.println('X');
        }
        //any code here in the first try block 
        //is unreachable if an exception occurs in the second try block
    }
    catch(Exception e)
    {
        System.out.println('Y');
    }
    finally
    {
        System.out.println('Z');
    }
  }
}

ผลลัพธ์ใน

A
B
X
Y
Z

6

บล็อกสุดท้ายจะทำงานหลังจากการบล็อกการลองสิ้นสุดลงเสมอไม่ว่าการพยายามจะสิ้นสุดลงตามปกติหรือผิดปกติเนื่องจากมีข้อยกเว้นเอ้อโยนได้

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

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

บังเอิญลอง / ในที่สุดก็เป็นเรื่องธรรมดาที่ต้องทำสำหรับการจัดการทรัพยากรเนื่องจาก java ไม่มีตัวทำลาย

เช่น -

r = new LeakyThing();
try { useResource( r); }
finally { r.release(); }  // close, destroy, etc

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

catch ( Exception e) ...  // doesn't really catch *all*, eh?

ทำสิ่งนี้แทน:

catch ( Throwable t) ...

ดูคำตอบของ Carlos Heuberger ด้านล่างสำหรับส่วนที่น่าเกลียด
mplwork

3

เวอร์ชัน Java ก่อนเวอร์ชัน 7 อนุญาตให้มีการลองจับในที่สุดสามชุดนี้...

try - catch
try - catch - finally
try - finally

finally บล็อกจะถูกดำเนินการเสมอไม่ว่าจะเกิดอะไรขึ้นในไฟล์ tryหรือ / และcatchบล็อก ดังนั้นหากไม่มีการcatchบล็อกข้อยกเว้นจะไม่ได้รับการจัดการที่นี่

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

  • Java try block ต้องตามด้วย catch หรือ block ในที่สุด
  • สำหรับบล็อกการลองแต่ละครั้งอาจมีบล็อกที่เป็นศูนย์หรือมากกว่านั้น แต่สุดท้ายจะมีเพียงบล็อกเดียวเท่านั้น
  • บล็อกสุดท้ายจะไม่ถูกดำเนินการหากโปรแกรมออก (ไม่ว่าจะโดยเรียก System.exit () หรือทำให้เกิดข้อผิดพลาดร้ายแรงที่ทำให้กระบวนการยกเลิก)

1
"ก่อนเวอร์ชัน 7 อนุญาต" หมายความว่า Java 7 และ Java 8 ไม่อนุญาตให้ใช้ชุดค่าผสมทั้งสามนี้หรือไม่ ฉันสงสัยว่านั่นคือสิ่งที่คุณหมายถึง แต่นั่นคือความหมายของคำตอบของคุณ
Loduwijk

ในที่สุดบล็อกจะถูกดำเนินการหรือไม่หากมีคำสั่ง return ใน try block
Rahul Yadav

@ ราหุลใช่ที่สุดจะเรียกว่า Ref: stackoverflow.com/questions/65035/…
roottraveller

1
@Aaron - ไวยากรณ์ใหม่สำหรับ try-with-resource ซึ่งจะเรียก. close () โดยอัตโนมัติกับสิ่งที่สร้างภายใน parens หลังจากคำสำคัญ try
Roboprog

2

การบล็อกลองทำงานอย่างไรหากพบข้อยกเว้นหรือสิ่งใดที่สามารถโยนได้

ข้อยกเว้นจะถูกโยนออกจากบล็อกเช่นเดียวกับในกรณีอื่น ๆ ที่ไม่ถูกจับ

สุดท้ายบล็อกจะถูกดำเนินการโดยไม่คำนึงถึงวิธีการออกจากบล็อกลอง - ไม่ว่าจะมีการจับที่ใด ๆ ก็ตามไม่ว่าจะมีการจับคู่หรือไม่ก็ตาม

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


1

คุณไม่ลองกับโปรแกรมนั้นหรือ? ในที่สุดมันก็จะบล็อกและดำเนินการบล็อกในที่สุด แต่จะไม่มีการจัดการข้อยกเว้น แต่ข้อยกเว้นนั้นสามารถลบล้างได้ในบล็อกสุดท้าย!


1

ในที่สุดบล็อกจะดำเนินการหลังจากบล็อกการลองเสร็จสิ้น หากมีบางสิ่งถูกโยนเข้าไปในบล็อกลองเมื่อออกจากบล็อกในที่สุดก็จะถูกดำเนินการ


0

ภายในtryบล็อกเราเขียนรหัสที่สามารถทำให้เกิดข้อยกเว้นได้ catchบล็อกเป็นที่ที่เราจัดการข้อยกเว้น finallyบล็อกจะถูกดำเนินการเสมอไม่ว่ายกเว้นเกิดขึ้นหรือไม่

ตอนนี้ถ้าเรามีการบล็อกในที่สุดแทนที่จะเป็นบล็อกแบบลองจับในที่สุดข้อยกเว้นจะไม่ได้รับการจัดการและหลังจากบล็อกการลองแทนที่จะควบคุมไปจับบล็อกมันจะไปบล็อกในที่สุด เราสามารถใช้ try-last block เมื่อเราไม่ต้องการทำอะไรเลยโดยมีข้อยกเว้น


0

ไม่ว่าข้อยกเว้นจะถูกโยนทิ้งหรือไม่อยู่ในtryบล็อก - finallyบล็อกจะถูกดำเนินการ ข้อยกเว้นจะไม่ถูกจับ

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