เมธอดที่โยน RuntimeException ควรระบุในเมธอดซิกเนเจอร์หรือไม่


86

ตัวอย่างเช่นหลายวิธีในกรอบ / JDK อาจโยน

java.lang.SecurityException 

แต่สิ่งนี้ไม่ได้ระบุไว้ในลายเซ็นของวิธีการ (เนื่องจากปกติแล้วจะสงวนไว้สำหรับข้อยกเว้นที่ตรวจสอบ) ฉันต้องการโต้แย้งว่าการประกาศ RuntimeExceptions ใน method sigs มีประโยชน์มากมาย (คล้ายกับการตรวจสอบประเภทคงที่เป็นต้น) ฉันเมาหรืออย่างอื่น?

คำตอบ:


70

ฉันจะไม่ประกาศข้อยกเว้นที่ไม่ได้เลือกไว้ในลายเซ็นเนื่องจากจะทำให้ผู้ใช้ API นั้นเข้าใจผิด ไม่ชัดเจนอีกต่อไปว่าต้องจัดการข้อยกเว้นอย่างชัดเจนหรือไม่

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


4
คอมไพเลอร์ java ไม่ได้บังคับให้คุณจัดการกับ RuntimeExceptions ที่ประกาศ ดังนั้นคุณสามารถประกาศได้โดยมีวัตถุประสงค์เพื่อเป็น "คำใบ้" สำหรับนักพัฒนา สามารถพูดคุยได้หาก JavaDoc เป็นสถานที่ที่ดีกว่าสำหรับสิ่งนั้น ประเด็นเกี่ยวกับข้อยกเว้นที่เลือกและไม่เลือกมีความสำคัญ ข้อยกเว้นที่ตรวจสอบและไม่ได้ทำเครื่องหมายคือสิ่งที่ Java หมายถึงจริงๆด้วย (Compiletime-) ข้อยกเว้น (การตรวจสอบ) และ RuntimeExceptions (ไม่เลือก)
Guardian667

6
ในฤดูใบไม้ผลิการประกาศข้อยกเว้นที่ไม่เลือกในลายเซ็นของวิธีการเริ่มต้นเป็นแนวทางปฏิบัติทั่วไป
johnlemon

39

จากบทช่วยสอน Oracle Java :

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

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


ดังนั้นคอมไพลเลอร์ไม่ต้องการให้คุณจับหรือระบุข้อยกเว้นรันไทม์ (แม้ว่าคุณจะทำได้)
johnlemon

18

ลองดู javadoc สำหรับ Collection # add

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

Throws:
UnsupportedOperationException - add is not supported by this collection.
ClassCastException - class of the specified element prevents it from being added to this collection.
NullPointerException - if the specified element is null and this collection does not support null elements.
IllegalArgumentException - some aspect of this element prevents it from being added to this collection.

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


6
คำตอบนี้ผิด คุณกำลังพูดถึงคำสั่ง Javadoc ในขณะที่คำถามเกี่ยวกับthrowsลายเซ็นของวิธีการ สิ่งเหล่านี้ไม่ใช่สิ่งเดียวกัน ใช่คุณควรบันทึกข้อยกเว้นทั้งหมดที่ API ของคุณส่งมา แต่คำถามไม่ได้เกี่ยวกับเรื่องนั้น
Gili

8

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

FYI: เมื่อเวลาผ่านไป (ตอนนี้ในปี 2017) ตอนนี้ฉันเอนเอียงมากขึ้นในการจัดทำเอกสารใน javadoc เท่านั้นและหลีกเลี่ยงข้อยกเว้นที่ตรวจสอบให้มากที่สุด


3

ในมุมมองของฉันไม่ควรระบุข้อยกเว้นที่ไม่เลือกไว้ในลายเซ็นของวิธีการเนื่องจากขัดกับธรรมชาติ

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


3

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


1

สิ่งนี้เกี่ยวข้องกับการอภิปรายเกี่ยวกับข้อยกเว้นที่ตรวจสอบแล้ว ส่วนใหญ่ยอมรับว่าไม่ควรประกาศข้อยกเว้นในลายเซ็นของวิธีการ

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


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

1
สิ่งที่ฉันพูดคือนักพัฒนาไม่ควรถูกบังคับให้ตรวจจับข้อยกเว้นที่ตรวจสอบ ดังนั้นจึงไม่จำเป็นต้องประกาศในลายเซ็นของวิธีการ ใน Java คุณสามารถแปลงเป็นข้อยกเว้นรันไทม์ได้ตามที่ Spring กำลังทำอยู่ ฉันกำลังบอกด้วยว่าข้อยกเว้นรันไทม์ควรถูกโยนทิ้งในสถานการณ์ที่ไม่สามารถกู้คืนได้เท่านั้น
kgiannakakis
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.