ความแตกต่างระหว่าง java.lang.RuntimeException และ java.lang.Exception


210

มีคนอธิบายความแตกต่างระหว่างjava.lang.RuntimeExceptionและjava.lang.Exception? ฉันจะตัดสินใจว่าจะขยายเวลาใดหากฉันสร้างข้อยกเว้นของตัวเอง

คำตอบ:


181

โดยทั่วไปRuntimeExceptionsเป็นข้อยกเว้นที่สามารถป้องกันได้โดยทางโปรแกรม เช่น ,NullPointerException ArrayIndexOutOfBoundExceptionหากคุณตรวจสอบnullก่อนโทรวิธีใด ๆNullPointerExceptionจะไม่เกิดขึ้น ในทำนองเดียวกันArrayIndexOutOfBoundExceptionจะไม่เกิดขึ้นหากคุณตรวจสอบดัชนีก่อน RuntimeExceptionไม่ได้ตรวจสอบโดยคอมไพเลอร์ดังนั้นจึงเป็นรหัสที่สะอาด

แก้ไข : คนสมัยนี้ชอบRuntimeExceptionเพราะรหัสสะอาดมันผลิต มันเป็นตัวเลือกส่วนบุคคลโดยสิ้นเชิง


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

4
ทุกวันนี้คนนิยมใช้ RuntimeException แบบไม่ จำกัด เนื่องจากมันเข้ากันได้กับการประมวลผล Java 8 Lambda ในขณะที่ข้อยกเว้นที่ตรวจสอบประเภท Exception นั้นไม่ใช่
Hartmut P.

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

186

ใน Java มีข้อยกเว้นสองประเภท: ข้อยกเว้นที่ตรวจสอบและข้อยกเว้นที่ไม่ได้ตรวจสอบ ข้อยกเว้นที่ตรวจสอบจะต้องได้รับการจัดการอย่างชัดเจนโดยรหัสในขณะที่ข้อยกเว้นที่ไม่ได้ตรวจสอบไม่จำเป็นต้องได้รับการจัดการอย่างชัดเจน

สำหรับข้อยกเว้นที่เลือกคุณต้องใส่บล็อก try / catch รอบ ๆ โค้ดที่อาจทำให้เกิดข้อยกเว้นหรือเพิ่มส่วน "throws" ลงในเมธอดเพื่อระบุว่าวิธีนี้อาจทำให้เกิดข้อยกเว้นประเภทนี้ (ซึ่งจะต้องเป็น จัดการในระดับการโทรหรือสูงกว่า)

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


3
จริงแล้วมันเป็นความจริงที่ว่า "มีข้อยกเว้นสองประเภท" แต่ทำไมเอกสารของ Oracle ถึงบอกว่ามีสามประเภท จะพิจารณาข้อผิดพลาดเป็นประเภทที่ 3 ฉันคิดว่าข้อผิดพลาดไม่ใช่ข้อยกเว้นเลยเพียง Throwable (วัตถุ) ใช่มันเลียนแบบพฤติกรรมของข้อยกเว้นรันไทม์ คุณจะพูดอะไรเกี่ยวกับเรื่องนี้? Oracle doc อ้าง docs.oracle.com/javase/tutorial/essential/exceptions/ …
Asif Shahzad

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

5
แต่เรื่องตลกคือ RunTimeException นั้นขยายออกไปข้อยกเว้น: D (ฉันรู้ว่านี่ไม่ได้ทำให้เกิดปัญหาใด ๆ และ JVM จะดูแลบริบททั้งหมด)
Alireza Mohamadi

94

ก่อนที่จะดูความแตกต่างระหว่างjava.lang.RuntimeExceptionและjava.lang.Exceptionคลาสคุณต้องทราบExceptionลำดับชั้น ทั้งคลาสExceptionและErrorมาจากคลาสThrowable(ซึ่งมาจากคลาสObject) และชั้นเรียนมาจากชั้นRuntimeExceptionException

ข้อยกเว้นทั้งหมดจะได้มาทั้งจากหรือExceptionRuntimeException

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

ดังนั้นทุกข้อยกเว้นที่กองกำลังเรียบเรียงให้คุณจับได้มาโดยตรงจากjava.lang.Exceptionและอื่น ๆ java.lang.RuntimeExceptionทั้งหมดซึ่งคอมไพเลอร์ไม่ได้บังคับให้คุณจับได้มาจาก

ต่อไปนี้คือบางส่วนของ subclasses ที่รู้จักกันโดยตรงของRuntimeException

AnnotationTypeMismatchException,
ArithmeticException,
ArrayStoreException,
BufferOverflowException,
BufferUnderflowException,
CannotRedoException,
CannotUndoException,
ClassCastException,
CMMException,
ConcurrentModificationException,
DataBindingException,
DOMException,
EmptyStackException,
EnumConstantNotPresentException,
EventException,
IllegalArgumentException,
IllegalMonitorStateException,
IllegalPathStateException,
IllegalStateException,
ImagingOpException,
IncompleteAnnotationException,
IndexOutOfBoundsException,
JMRuntimeException,
LSException,
MalformedParameterizedTypeException,
MirroredTypeException,
MirroredTypesException,
MissingResourceException,
NegativeArraySizeException,
NoSuchElementException,
NoSuchMechanismException,
NullPointerException,
ProfileDataException,
ProviderException,
RasterFormatException,
RejectedExecutionException,
SecurityException,
SystemException,
TypeConstraintException,
TypeNotPresentException,
UndeclaredThrowableException,
UnknownAnnotationValueException,
UnknownElementException,
UnknownTypeException,
UnmodifiableSetException,
UnsupportedOperationException,
WebServiceException 

47

มีการตรวจสอบข้อยกเว้นและ RuntimeException ไม่ถูกตรวจสอบ

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

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


15

คลาสยกเว้นของรันไทม์ (RuntimeException และคลาสย่อย) ได้รับการยกเว้นจากการตรวจสอบเวลาคอมไพล์เนื่องจากคอมไพเลอร์ไม่สามารถสร้างข้อยกเว้นรันไทม์ที่ไม่สามารถเกิดขึ้นได้ (จาก JLS)

ในคลาสที่คุณออกแบบคุณควรคลาสย่อยExceptionและส่งอินสแตนซ์ของมันเพื่อส่งสัญญาณสถานการณ์พิเศษต่างๆ การทำเช่นนั้นคุณจะส่งสัญญาณลูกค้าของชั้นเรียนของคุณอย่างชัดเจนว่าการใช้ชั้นเรียนของคุณอาจทำให้เกิดข้อยกเว้นและพวกเขาต้องทำตามขั้นตอนเพื่อจัดการสถานการณ์พิเศษ

ตัวอย่างโค้ดด้านล่างอธิบายจุดนี้:

//Create your own exception class subclassing from Exception
class MyException extends Exception {
    public MyException(final String message) {
        super(message);
    }
}

public class Process {
    public void execute() {
        throw new RuntimeException("Runtime");
    }  
    public void process() throws MyException {
        throw new MyException("Checked");
    }
}

ในการกำหนดระดับของชั้นดังกล่าวข้างต้นกระบวนการวิธีการที่executeสามารถโยนRuntimeExceptionแต่ไม่ใช่วิธีการประกาศจำเป็นต้องระบุว่ามันจะพ่นRuntimeException

วิธีการprocessโยนข้อยกเว้นที่ตรวจสอบและควรประกาศว่าจะโยนข้อยกเว้นที่ตรวจสอบประเภทMyExceptionและไม่ทำเช่นนั้นจะเป็นข้อผิดพลาดในการรวบรวม

นิยามคลาสข้างต้นจะมีผลกับรหัสที่ใช้คลาสProcessเช่นกัน

การเรียกnew Process().execute()เป็นการเรียกใช้ที่ถูกต้องเนื่องจากการเรียกใช้แบบฟอร์ม new Process().process()ทำให้เกิดข้อผิดพลาดในการคอมไพล์ นี่เป็นเพราะรหัสลูกค้าควรทำตามขั้นตอนในการจัดการMyException(พูดการเรียกไปยังกระบวนการ () สามารถอยู่ใน try / catch block)


13

ใช้ RuntimeException อย่างเหมาะสมหรือไม่

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

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

โปรดทราบว่าข้อยกเว้นที่ไม่ได้เลือกเป็นหนึ่งที่ได้มาจากและข้อยกเว้นการตรวจสอบเป็นหนึ่งที่ได้มาจากRuntimeExceptionException

ทำไมต้องโยน a RuntimeExceptionหากลูกค้าไม่สามารถทำอะไรเพื่อกู้คืนจากข้อยกเว้น? บทความอธิบาย:

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


5

จากเอกสาร oracle:

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

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

RuntimeExceptions เป็นเหมือน "ข้อยกเว้นจากการใช้ API ที่ไม่ถูกต้อง" ตัวอย่างของ runtimeexceptions: IllegalStateException, NegativeArraySizeException, NullpointerException

ด้วยข้อยกเว้นคุณต้องจับมันอย่างชัดเจนเพราะคุณยังสามารถทำบางสิ่งบางอย่างในการกู้คืน ตัวอย่างของข้อยกเว้นคือ: IOException, TimeoutException, PrintException ...


4

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


3

RuntimeException เป็นคลาสลูกของคลาสข้อยกเว้น

นี่เป็นหนึ่งในคลาสย่อยของคลาส Exception RuntimeException เป็นซูเปอร์คลาสของข้อยกเว้นเหล่านั้นที่สามารถโยนได้ระหว่างการทำงานปกติของ Java Virtual Machine วิธีการไม่จำเป็นต้องประกาศในการส่งประโยคย่อยคลาสใด ๆ ของ RuntimeException ที่อาจถูกโยนทิ้งในระหว่างการดำเนินการของวิธีการ แต่ไม่ถูกจับ

ลำดับชั้นคือ

java.lang.Object

--- java.lang.Throwable

------- java.lang.Exception

------------- java.lang.RuntimeException


0

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

หากต้องการบรรลุอินเตอร์เฟสที่สะอาดให้ใช้การสืบทอดเพื่อแบ่งประเภทย่อยของข้อยกเว้นชนิดต่าง ๆ ที่แอ็พพลิเคชันของคุณมีแล้วแสดงข้อยกเว้นพาเรนต์


0

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


0
  1. ข้อยกเว้นที่ผู้ใช้กำหนดสามารถเป็น Checked Exception หรือ Unchecked Exception ขึ้นอยู่กับคลาสที่ขยาย

  2. ข้อยกเว้นที่ผู้ใช้กำหนดสามารถเป็นข้อยกเว้นแบบกำหนดเองที่ตรวจสอบได้หากมันขยายไปถึงคลาสข้อยกเว้น

  3. ข้อยกเว้นที่ผู้ใช้กำหนดสามารถเป็นข้อยกเว้นแบบกำหนดเองที่กำหนดเองได้หากขยายไปยังคลาสข้อยกเว้นรันไทม์

  4. กำหนดชั้นเรียนและทำให้เด็กเป็น Exception หรือ Run time Exception

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