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


142

ในรหัสนี้จะsomeVarถูกตั้งค่าแม้ว่าบล็อก catch จะถูกดำเนินการและข้อยกเว้นที่สองจะถูกโยนทิ้ง?

public void someFunction() throws Exception {
    try {
        //CODE HERE
    } catch (Exception e) {
        Log.e(TAG, "", e);
        throw new Exception(e);
    } finally {
        this.someVar= true;
    }
}

2
เนื่องจากมีสถานการณ์ที่พฤติกรรมไม่เป็นไปตามที่ระบุไว้โดย @GaryF
jax

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

คำตอบ:


184

ใช่บล็อกสุดท้ายจะทำงานเสมอ ... ยกเว้นเมื่อ:

  • เธรดที่ใช้บล็อก try-catch-สุดท้ายถูกฆ่าหรือขัดจังหวะ
  • คุณใช้ System.exit(0);
  • VM พื้นฐานถูกทำลายด้วยวิธีอื่น
  • ฮาร์ดแวร์พื้นฐานไม่สามารถใช้งานได้ในบางวิธี

นอกจากนี้หากวิธีการในบล็อกสุดท้ายของคุณส่งข้อยกเว้นที่ไม่ได้ตรวจสอบจะไม่มีการดำเนินการใด ๆ หลังจากนั้น (เช่นข้อยกเว้นจะถูกโยนทิ้งเหมือนที่ทำในรหัสอื่น) java.sql.Connection.close()กรณีที่พบบ่อยมากที่เกิดเหตุการณ์นี้คือ

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


4
คุณหมายถึงอะไรที่นี่โดย "เธรดที่เรียกใช้บล็อก try-catch-สุดท้ายคือ [... ] ขัดจังหวะ"? บางทีเอกสารนั้นเป็น worded ไม่ดี แต่ Thread.interrupt () จะไม่ทำให้บล็อกสุดท้ายถูกข้ามไม่ว่าจะถูกโยนจากการลองหรือ catch block การใช้สิ่งนี้ "ขัดจังหวะ" เพื่อหมายถึงบางสิ่งที่มีความรุนแรงมากกว่าเช่น Thread.stop () หรือไม่
Joe Kearney

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

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

1
@Stephen C - อันที่จริงมาจากการสอน JavaSE (เชื่อมโยงโดยคนอื่น ๆ ) มันอาจจะพูดคล้าย ๆ กันใน JLS แต่ฉันไม่พบส่วนที่เกี่ยวข้อง ฉันคาดหวังไว้ในบทที่ 11 (ข้อยกเว้น) บทที่ 14 (ข้อความ) หรือบทที่ 15 (นิพจน์) แต่ไม่เห็นสิ่งใดที่เกี่ยวข้องกับการขัดจังหวะอย่างชัดเจน ฉันสนใจที่จะเห็นสิ่งนั้นอย่างแน่นอน
GaryF

1
@GaryF - ฉันเห็น ที่จริงแล้ว JLS พูดเกี่ยวกับการยกเลิกคำสั่ง "ปกติ" และ "ฉับพลัน" และมีส่วน (14.1) ที่กำหนดคำศัพท์ พฤติกรรมของfinallyถูกระบุในแง่ของการยุติแบบปกติและฉับพลัน
Stephen C

10

ใช่.

ดูเอกสารประกอบ :

บล็อกสุดท้ายจะเรียกใช้งานเสมอเมื่อบล็อกลองออก

ข้อยกเว้น

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


2

ในที่สุดบล็อกดำเนินการเสมอ

public class ExceptionTest {

public static void someFunction(String input) throws Exception {
    try {
        if( input.equals("ABC") ) {
            System.out.println("Matched");
        }
    } catch (Exception e) {
        throw new Exception(e);
    } finally {
        System.out.println("Input Is "+input+" Finally Executed!!!");
    }
}

/**
 * @param args
 */
public static void main(String[] args) {
    // TODO Auto-generated method stub
    try {
        System.out.println("********* Test with VALUE ********* ");
        someFunction("ABC");
        System.out.println("\r\n********* Test with NULL  ********* ");
        someFunction(null);
    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

}

Java ลองจับในที่สุดบล็อกด้วยการโยน


2

ในที่สุดก็จะถูกประหารชีวิตเสมอไม่ว่ากรณีของคุณจะเป็นเช่นไร

  • ลองจับในที่สุดบล็อก
  • พ่น

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

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



1

ใช่. finallyบล็อกดำเนินการเสมอยกเว้นกรณีที่คุณเรียก System.exit () เพราะมันหยุด Java VM


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