कब चुने और अनियंत्रित अपवादों का चयन करें


213

जावा में (या चेक किए गए अपवादों के साथ कोई अन्य भाषा), अपना खुद का अपवाद वर्ग बनाते समय, आप यह कैसे तय करते हैं कि इसे चेक किया जाना चाहिए या अनियंत्रित होना चाहिए?

मेरी वृत्ति यह है कि जिन मामलों में कॉलर कुछ उत्पादक तरीके से पुनर्प्राप्त करने में सक्षम हो सकता है, उनके लिए एक अपवादित अपवाद को बुलाया जाएगा, जहां एक अनियंत्रित अपवाद अपरिवर्तनीय मामलों के लिए अधिक होगा, लेकिन मुझे दूसरे के विचारों में दिलचस्पी होगी।


11
बैरी रूज़ेक ने चेक या अनियंत्रित अपवादों को चुनने के बारे में एक उत्कृष्ट मार्गदर्शिका लिखी है।
12

जवाबों:


241

चेक किए गए अपवाद महान हैं, इसलिए जब तक आप समझते हैं कि उनका उपयोग कब किया जाना चाहिए। जावा कोर एपीआई SQLException (और कभी-कभी IOException के लिए) इन नियमों का पालन करने में विफल रहता है, यही वजह है कि वे इतने भयानक हैं।

चेक किए गए अपवादों का उपयोग पूर्वानुमान के लिए किया जाना चाहिए , लेकिन अपरिहार्य त्रुटियां जो इससे उबरने के लिए उचित हैं ।

अनियंत्रित अपवादों को हर चीज के लिए इस्तेमाल किया जाना चाहिए।

मैं आपके लिए इसे तोड़ दूंगा, क्योंकि ज्यादातर लोग इसका गलत मतलब निकालते हैं।

  1. प्रीडिक्टेबल लेकिन अप्राप्य : कॉल करने वाले ने इनपुट मापदंडों को मान्य करने के लिए अपनी शक्ति के भीतर सब कुछ किया, लेकिन उनके नियंत्रण से बाहर की कुछ स्थिति ने ऑपरेशन को विफल कर दिया है। उदाहरण के लिए, आप किसी फ़ाइल को पढ़ने का प्रयास करते हैं, लेकिन कोई इसे आपके द्वारा जांचे जाने के समय के बीच हटा देता है यदि यह मौजूद है और जिस समय रीड ऑपरेशन शुरू होता है। एक चेक किए गए अपवाद को घोषित करके, आप कॉल करने वाले को इस विफलता का अनुमान लगाने के लिए कह रहे हैं।
  2. इससे उबरने का उचित कारण : अपवादों को प्रत्याशित करने के लिए कॉल करने वालों से कोई मतलब नहीं है कि वे इससे उबर नहीं सकते। यदि कोई उपयोगकर्ता गैर-मौजूदा फ़ाइल से पढ़ने का प्रयास करता है, तो कॉलर उन्हें नए फ़ाइल नाम के लिए संकेत दे सकता है। दूसरी ओर, यदि प्रोग्रामिंग बग (अवैध विधि तर्क या बगिया विधि कार्यान्वयन) के कारण विधि विफल हो जाती है, तो मध्य-निष्पादन में समस्या को ठीक करने के लिए कुछ भी नहीं किया जा सकता है। सबसे अच्छा यह कर सकता है कि समस्या को लॉग किया जाए और बाद में इसे ठीक करने के लिए डेवलपर की प्रतीक्षा करें।

जब तक आप जो अपवाद फेंक रहे हैं , वह उपरोक्त सभी शर्तों को पूरा करता है, तो उन्हें अनियंत्रित अपवाद का उपयोग करना चाहिए।

हर स्तर पर पुनर्मूल्यांकन : कभी-कभी जाँच किए गए अपवाद को पकड़ने वाली विधि त्रुटि को संभालने के लिए सही जगह नहीं है। उस स्थिति में, अपने स्वयं के कॉल करने वालों के लिए क्या उचित है, इस पर विचार करें। यदि अपवाद उनके लिए पुनर्प्राप्त करने के लिए अनुमानित, अप्राप्य और उचित है, तो आपको स्वयं एक अपवाद छोड़ देना चाहिए। यदि नहीं, तो आपको अपवाद को अनियंत्रित अपवाद में लपेटना चाहिए। यदि आप इस नियम का पालन करते हैं, तो आप अपने आप को अनियंत्रित अपवादों के लिए जाँच किए गए अपवादों को परिवर्तित कर पाएंगे और इसके विपरीत कि आप किस परत में हैं।

चेक किए गए और अनियंत्रित अपवाद दोनों के लिए, सही अमूर्त स्तर का उपयोग करें । उदाहरण के लिए, दो अलग-अलग कार्यान्वयन (डेटाबेस और फाइल सिस्टम) के साथ एक कोड रिपॉजिटरी को फेंकने SQLExceptionया लागू करने से कार्यान्वयन-विशिष्ट विवरण को उजागर करने से बचना चाहिए IOException। इसके बजाय, इसे एक अमूर्त में अपवाद को लपेटना चाहिए जो सभी कार्यान्वयन (जैसे RepositoryException) को फैलाता है ।


2
"आप किसी फ़ाइल को पढ़ने का प्रयास करते हैं, लेकिन कोई आपके द्वारा जांचे जाने के समय के बीच इसे हटा देता है यदि यह मौजूद है और जिस समय रीड ऑपरेशन शुरू होता है।" => यह भी 'अपेक्षित' कैसे है? मेरे लिए यह अधिक लगता है: अनपेक्षित और रोके जाने योग्य .. जो केवल 2 बयानों के बीच एक फ़ाइल को हटाने की उम्मीद करेगा?
कोरे तुगये

9
@KorayTugay उम्मीद नहीं है कि परिदृश्य विशिष्ट है। इसका सिर्फ यह अर्थ है कि हम समय से पहले होने वाली इस त्रुटि को दूर कर सकते हैं (प्रोग्रामिंग त्रुटियों के साथ जिसकी भविष्यवाणी समय से पहले नहीं की जा सकती है)। अप्राप्य इस तथ्य को संदर्भित करता है कि ऐसा कुछ भी नहीं है जो प्रोग्रामर उपयोगकर्ता या अन्य अनुप्रयोगों को उस समय के बीच किसी फ़ाइल को हटाने से रोकने के लिए कर सकता है जो हम जांचते हैं कि क्या यह मौजूद है और समय जब रीड ऑपरेशन शुरू होता है।
जिली

तो विधि के भीतर किसी भी डेटाबेस से संबंधित मुद्दों की जाँच अपवाद छोड़ देना चाहिए?
ivanjermakov

59

से एक जावा लर्नर :

जब कोई अपवाद होता है, तो आपको अपवाद को पकड़ना होगा या संभालना होगा, या संकलक को बताना होगा कि आप यह घोषित करके नहीं संभाल सकते हैं कि आपकी विधि उस अपवाद को फेंकती है, फिर आपके विधि का उपयोग करने वाले कोड को उस अपवाद को संभालना होगा (यहां तक ​​कि यह भी यह भी घोषित कर सकता है कि यह अपवाद को फेंकता है यदि वह इसे नहीं संभाल सकता है)।

कंपाइलर जांच करेगा कि हमने दो चीजों में से एक किया है (पकड़ना, या घोषित करना)। अतः इन्हें Checked अपवाद कहा जाता है। लेकिन त्रुटियों और रनटाइम अपवादों को संकलक द्वारा चेक नहीं किया जाता है (भले ही आप पकड़ने के लिए चुन सकते हैं, या घोषित कर सकते हैं, इसकी आवश्यकता नहीं है)। तो, इन दोनों को अनियंत्रित अपवाद कहा जाता है।

त्रुटियों का उपयोग उन स्थितियों का प्रतिनिधित्व करने के लिए किया जाता है जो अनुप्रयोग के बाहर होती हैं, जैसे कि सिस्टम का क्रैश। रनटाइम अपवाद आमतौर पर एप्लिकेशन लॉजिक में गलती से होते हैं। आप इन स्थितियों में कुछ नहीं कर सकते। जब रनटाइम अपवाद होता है, तो आपको अपना प्रोग्राम कोड फिर से लिखना होगा। इसलिए, इनकी जाँच कंपाइलर द्वारा नहीं की जाती है। ये रनटाइम अपवाद विकास, और परीक्षण अवधि को उजागर करेंगे। फिर हमें इन त्रुटियों को दूर करने के लिए अपना कोड रिफलेक्टर करना होगा।


13
वह रूढ़िवादी दृष्टिकोण है। लेकिन इसे लेकर काफी विवाद है।
आर्टब्रिस्टल

49

मेरे द्वारा उपयोग किया जाने वाला नियम है: कभी भी अनियंत्रित अपवादों का उपयोग न करें! (या जब आपको इसके आसपास कोई रास्ता दिखाई न दे)

विपरीत के लिए एक बहुत मजबूत मामला है: कभी भी जाँच किए गए अपवादों का उपयोग न करें। मैं बहस में पक्ष लेने के लिए अनिच्छुक हूं, लेकिन व्यापक सर्वसम्मति से प्रतीत होता है कि चेक किए गए अपवादों को पेश करना एक गलत निर्णय था। कृपया मैसेंजर को शूट न करें और उन तर्कों को देखें ।


3
आईएमएचओ, जाँच किए गए अपवाद एक प्रमुख संपत्ति हो सकते थे यदि किसी विधि के लिए यह घोषित करने का एक आसान तरीका था कि यह कुछ अपवादों (या किसी भी) को फेंकने के लिए कोड के किसी विशेष ब्लॉक में बुलाए गए तरीकों की उम्मीद नहीं कर रहा है, और यह कि कोई भी चेक किया गया ऐसी अपेक्षाओं के विपरीत फेंके जाने वाले अपवादों को कुछ अन्य अपवाद प्रकारों में लपेटा जाना चाहिए और पुनर्विचार करना चाहिए। मैं चाहता हूं कि 90% समय जब कोड को एक चेक किए गए अपवाद के साथ सामना करने के लिए तैयार नहीं किया जाता है, इस तरह के रैप-एंड-रीथ्रो इसे संभालने का सबसे अच्छा तरीका होगा, लेकिन क्योंकि इसका कोई भाषा समर्थन नहीं है, जो शायद ही कभी किया गया हो।
सुपरकाट

@supercat अनिवार्य रूप से यह है: मैं सख्त प्रकार की जाँच और जाँच किए गए अपवादों का एक डाई-हार्ड प्रशंसक हूं, इसका एक तार्किक विस्तार है। मैंने पूरी तरह से जाँच अपवादों को छोड़ दिया है, भले ही मैं उन्हें बहुत पसंद करता हूं।
कोनराड रुडोल्फ

1
एक peeve मेरे पास अपवादों के डिजाइन के साथ है, जिसे मैंने वर्णित तंत्र को हल किया है, यह है कि यदि फ़ाइल के अंत में पढ़ते समय fooफेंकने के रूप में प्रलेखित किया जाता है barException, और fooएक ऐसी विधि को कॉल करता है जो फेंकता है, barExceptionभले ही fooवह इसकी उम्मीद न कर रहा हो, कोड जो कॉल fooकरेगा सोचता है कि फ़ाइल का अंत पहुंच गया था, और कोई सुराग नहीं होगा कि कुछ अप्रत्याशित हुआ। मैं उस स्थिति पर विचार करूँगा जहाँ जाँच की गई अपवादों में से सबसे अधिक उपयोगी होनी चाहिए , लेकिन यह एकमात्र ऐसा मामला है जहाँ संकलक बिना जाँच किए अपवादों को अनुमति देगा।
सुपरकैट

@ सुपरकार्ट: कोड के लिए पहले से ही एक आसान तरीका है कि आप पहली टिप्पणी में क्या चाहते हैं: कोड को एक कोशिश ब्लॉक में लपेटें, अपवाद को पकड़ें, और अपवाद को एक रनटाइम एक्सेप्शन और रेथ्रो में लपेटें।
वॉरेन ड्यू

1
@KonradRudolph सुपरकैट को "कोड का एक विशेष ब्लॉक" कहा जाता है; ब्लॉक को परिभाषित किया जाना चाहिए, घोषणात्मक वाक्यविन्यास ब्लोट को कम नहीं करेगा। यदि आप सोच रहे हैं कि यह पूरे समारोह के लिए घोषणात्मक होगा, तो यह खराब प्रोग्रामिंग को प्रोत्साहित करेगा क्योंकि लोग केवल घोषणा में चिपके रहेंगे क्योंकि वास्तव में चेक किए गए अपवादों को संभावित रूप से पकड़ा हुआ दिख रहा है, और सुनिश्चित करें कि कोई और बेहतर तरीका नहीं है। उन्हें संभालने के लिए।
वॉरेन डेव

46

किसी भी बड़ी पर्याप्त प्रणाली पर, कई परतों के साथ, अपवादित अपवाद बेकार है, वैसे भी, आपको यह संभालने के लिए वास्तु स्तर की रणनीति की आवश्यकता है कि अपवाद को कैसे नियंत्रित किया जाएगा (एक गलती बाधा का उपयोग करें)

चेक किए गए अपवादों के साथ आपकी त्रुटि से निपटने के लिए सूक्ष्म प्रबंधन किया जाता है और किसी भी बड़ी प्रणाली पर इसका असहनीय असर होता है।

यदि आप किसी त्रुटि को "पुनर्प्राप्त करने योग्य" नहीं जानते हैं, तो अधिकांश समय आप यह नहीं जानते हैं कि आपके एपीआई का कॉलर किस परत में स्थित है।

मान लीजिए कि मैं एक StringToInt API बनाता हूं, जो पूर्णांक के स्ट्रिंग प्रतिनिधित्व को इंट में परिवर्तित करता है। यदि एपीआई "फू" स्ट्रिंग के साथ कहा जाता है, तो क्या मुझे एक जाँच अपवाद छोड़ देना चाहिए? क्या यह पुनर्प्राप्त करने योग्य है? मुझे नहीं पता, क्योंकि उसकी परत में मेरे स्ट्रिंगटॉइंट एपीआई के कॉलर पहले से ही इनपुट को मान्य कर सकते हैं, और अगर इस अपवाद को फेंक दिया जाए तो यह बग या डेटा भ्रष्टाचार है और यह इस परत के लिए पुनर्प्राप्त करने योग्य नहीं है।

इस मामले में एपीआई का कॉलर अपवाद को पकड़ना नहीं चाहता है। वह केवल अपवाद को "बबल अप" करने देना चाहता है। अगर मैंने एक चेक किया हुआ अपवाद चुना, तो इस कॉल करने वाले के पास बेकार के ब्‍लॉक ब्‍लॉक ही होंगे, जो कृत्रिम रूप से अपवाद को रद कर देंगे।

जो रिकवर करने योग्य है वह अधिकतर एपीआई के कॉलर पर निर्भर करता है, एपीआई के राइट पर नहीं। एक एपीआई को चेक किए गए अपवादों का उपयोग नहीं करना चाहिए क्योंकि केवल अनियंत्रित अपवाद अपवाद को पकड़ने या अनदेखा करने की अनुमति देता है।



16
@alexsmail इंटरनेट मुझे आश्चर्यचकित करने में कभी विफल नहीं होता है, वास्तव में यह मेरा ब्लॉग है :)
स्टीफन

30

तुम सही हो।

अनियंत्रित अपवादों का उपयोग सिस्टम को तेजी से विफल होने के लिए किया जाता है जो एक अच्छी बात है। आपको स्पष्ट रूप से बताना चाहिए कि ठीक से काम करने के लिए आपकी विधि क्या है। इस तरह आप केवल एक बार इनपुट को मान्य कर सकते हैं।

उदाहरण के लिए:

/**
 * @params operation - The operation to execute.
 * @throws IllegalArgumentException if the operation is "exit"
 */
 public final void execute( String operation ) {
     if( "exit".equals(operation)){
          throw new IllegalArgumentException("I told you not to...");
     }
     this.operation = operation; 
     .....  
 }
 private void secretCode(){
      // we perform the operation.
      // at this point the opreation was validated already.
      // so we don't worry that operation is "exit"
      .....  
 }

बस एक उदाहरण रखना है। मुद्दा यह है कि यदि सिस्टम तेजी से विफल होता है, तो आपको पता चल जाएगा कि यह कहां और क्यों विफल हुआ। आपको एक स्टैकट्रेस मिलेगा जैसे:

 IllegalArgumentException: I told you not to use "exit" 
 at some.package.AClass.execute(Aclass.java:5)
 at otherPackage.Otherlass.delegateTheWork(OtherClass.java:4569)
 ar ......

और आपको पता चल जाएगा कि क्या हुआ था। अन्य प्रतिनिधि "डेलिगेटवॉर्क" विधि (लाइन 4569 पर) ने आपकी कक्षा को "बाहर निकलें" मूल्य के साथ बुलाया, तब भी जब इसे नहीं करना चाहिए आदि।

अन्यथा आपको अपने कोड पर सभी मान्यताओं को छिड़कना होगा और यह त्रुटि प्रवण है। इसके अलावा, कभी-कभी यह ट्रैक करना मुश्किल होता है कि क्या गलत हुआ और आप निराशा की डीबगिंग के घंटों की उम्मीद कर सकते हैं

समान बात NullPointerException के साथ होती है। यदि आपके पास कुछ 15 विधियों के साथ 700 लाइनें वर्ग हैं, जो 30 विशेषताओं का उपयोग करता है और उनमें से कोई भी अशक्त नहीं हो सकता है, तो उन सभी तरीकों में से प्रत्येक को वैधता के लिए मान्य करने के बजाय, आप उन सभी विशेषताओं को केवल पढ़ सकते हैं और उन्हें निर्माता में मान्य कर सकते हैं या फैक्टरी विधि।

 public static MyClass createInstane( Object data1, Object data2 /* etc */ ){ 
      if( data1 == null ){ throw NullPointerException( "data1 cannot be null"); }

  }


  // the rest of the methods don't validate data1 anymore.
  public void method1(){ // don't worry, nothing is null 
      ....
  }
  public void method2(){ // don't worry, nothing is null 
      ....
  }
  public void method3(){ // don't worry, nothing is null 
      ....
  }

जाँच किए गए अपवाद तब उपयोगी होते हैं जब प्रोग्रामर (आप या आपके सहकर्मी) ने सबकुछ सही किया, इनपुट को मान्य किया, परीक्षण किए, और सभी कोड सही हैं, लेकिन कोड किसी तीसरे पक्ष के वेबसर्वर से कनेक्ट होता है जो नीचे हो सकता है (या फ़ाइल आप उपयोग कर रहे थे (एक अन्य बाहरी प्रक्रिया आदि द्वारा हटा दिया गया था)। कनेक्शन का प्रयास करने से पहले webservice भी मान्य हो सकती है, लेकिन डेटा ट्रांसफर के दौरान कुछ गलत हो गया।

उस परिदृश्य में ऐसा कुछ भी नहीं है जिसे आप या आपके सहकर्मी मदद के लिए कर सकते हैं। लेकिन फिर भी आपको कुछ करना होगा और एप्लिकेशन को उपयोगकर्ता की आंखों में सिर्फ मरने और गायब होने नहीं देना चाहिए। आप इसके लिए एक जांचे गए अपवाद का उपयोग करते हैं और अपवाद को संभालते हैं, ऐसा होने पर आप क्या कर सकते हैं ?, अधिकांश समय, बस त्रुटि को लॉग इन करने का प्रयास करने के लिए, संभवत: अपना काम (ऐप के काम) को बचाएं और उपयोगकर्ता को एक संदेश प्रस्तुत करें। । (साइट ब्लाबला नीचे है, कृपया बाद में पुनः प्रयास करें आदि)

यदि चेक किए गए अपवाद का उपयोग नहीं किया गया है (सभी विधियों के हस्ताक्षर में "थ्रो एक्ससेप्शन" जोड़कर), तो आपका कोड बहुत नाजुक हो जाएगा, क्योंकि हर कोई उस अपवाद को अनदेखा करेगा (क्योंकि बहुत सामान्य है) और कोड की गुणवत्ता गंभीरता से होगी समझौता किया।

यदि आप अनियंत्रित अपवाद का उपयोग करते हैं तो ऐसा ही कुछ होगा। उस कोड के उपयोगकर्ताओं को पता नहीं है कि अगर कुछ गलत हो सकता है तो बहुत कोशिश करें {...} पकड़ (थ्रोएबल टी) दिखाई देगा।


2
खूब कहा है! +1। यह हमेशा मुझे आश्चर्यचकित करता है कि यह अंतर कॉलर (अनियंत्रित) / कैली (चेक किया गया) अधिक स्पष्ट नहीं है ...
वॉन सी सी

19

यहाँ मेरे 'अंगूठे का अंतिम नियम' है।
मैं उपयोग करता हूं:

  • कॉलर के कारण विफलता के लिए मेरे तरीके के कोड के भीतर अनियंत्रित अपवाद (जिसमें एक स्पष्ट और पूर्ण प्रलेखन शामिल है )
  • कैली के कारण एक विफलता के लिए अपवाद की जाँच की कि मुझे अपने कोड का उपयोग करने के लिए किसी को भी स्पष्ट करने की आवश्यकता है

पिछले उत्तर की तुलना में, यह एक स्पष्ट तर्क है (जिस पर एक सहमत या असहमत हो सकता है) एक या दूसरे (या दोनों) अपवादों के उपयोग के लिए।


उन दोनों अपवादों के लिए, मैं अपने आवेदन के लिए अपने स्वयं के अनियंत्रित और जाँच किए गए अपवाद का निर्माण करूँगा (एक अच्छा अभ्यास, जैसा कि यहाँ उल्लेख किया गया है ), बहुत ही सामान्य अनियंत्रित अपवाद को छोड़कर (जैसे NullPointerException)

उदाहरण के लिए, नीचे दिए गए इस विशेष कार्य का लक्ष्य एक वस्तु,
जिसका अर्थ है (या यदि पहले से मौजूद है) बनाना है:

  • MUST को अस्तित्व में लाने / प्राप्त करने के लिए ऑब्जेक्ट का कंटेनर (CALLER की जिम्मेदारी
    = अनियंत्रित अपवाद, और इस फ़ंक्शन के लिए स्पष्ट jadadoc टिप्पणी)
  • अन्य पैरामीटर शून्य नहीं हो सकते हैं
    (कोडर पर रखने के लिए कोडर का विकल्प: कोडर शून्य पैरामीटर के लिए जांच नहीं करेगा लेकिन कोडर ऐसा नहीं करता है)
  • परिणाम शून्य नहीं हो सकता
    (जिम्मेदारी और कैली के कोड का विकल्प, पसंद जो कॉल करने वाले के लिए बहुत रुचि होगी
    => अपवाद की जाँच की क्योंकि हर कॉल करने वाले को एक निर्णय लेना होगा यदि ऑब्जेक्ट बनाया / पाया नहीं जा सकता है, और वह निर्णय संकलन समय पर लागू किया जाना चाहिए: वे इस संभावना से निपटने के बिना इस फ़ंक्शन का उपयोग नहीं कर सकते हैं, इस जाँच के अपवाद के साथ इसका मतलब है)।

उदाहरण:


/**
 * Build a folder. <br />
 * Folder located under a Parent Folder (either RootFolder or an existing Folder)
 * @param aFolderName name of folder
 * @param aPVob project vob containing folder (MUST NOT BE NULL)
 * @param aParent parent folder containing folder 
 *        (MUST NOT BE NULL, MUST BE IN THE SAME PVOB than aPvob)
 * @param aComment comment for folder (MUST NOT BE NULL)
 * @return a new folder or an existing one
 * @throws CCException if any problems occurs during folder creation
 * @throws AssertionFailedException if aParent is not in the same PVob
 * @throws NullPointerException if aPVob or aParent or aComment is null
 */
static public Folder makeOrGetFolder(final String aFoldername, final Folder aParent,
    final IPVob aPVob, final Comment aComment) throws CCException {
    Folder aFolderRes = null;
    if (aPVob.equals(aParent.getPVob() == false) { 
       // UNCHECKED EXCEPTION because the caller failed to live up
       // to the documented entry criteria for this function
       Assert.isLegal(false, "parent Folder must be in the same PVob than " + aPVob); }

    final String ctcmd = "mkfolder " + aComment.getCommentOption() + 
        " -in " + getPNameFromRepoObject(aParent) + " " + aPVob.getFullName(aFolderName);

    final Status st = getCleartool().executeCmd(ctcmd);

    if (st.status || StringUtils.strictContains(st.message,"already exists.")) {
        aFolderRes = Folder.getFolder(aFolderName, aPVob);
    }
    else {
        // CHECKED EXCEPTION because the callee failed to respect his contract
        throw new CCException.Error("Unable to make/get folder '" + aFolderName + "'");
    }
    return aFolderRes;
}

19

यह केवल अपवाद से उबरने की क्षमता की बात नहीं है। मेरी राय में, जो बात सबसे ज्यादा है, वह यह है कि कॉल करने वाले को अपवाद को पकड़ने में दिलचस्पी है या नहीं।

यदि आप अपने उपयोग के लिए कहीं और उपयोग की जाने वाली लाइब्रेरी लिखते हैं, या आपके आवेदन में निचले स्तर की परत है, तो अपने आप से पूछें कि क्या कॉलर को आपके अपवाद को पकड़ने (जानने के बारे में) में दिलचस्पी है। यदि वह नहीं है, तो एक अनियंत्रित अपवाद का उपयोग करें, ताकि आप उसे अनावश्यक रूप से बोझ न करें।

यह कई चौखटों द्वारा प्रयुक्त दर्शन है। वसंत और हाइबरनेट, विशेष रूप से, दिमाग में आते हैं - वे ज्ञात जांच अपवाद को अनियंत्रित अपवाद में परिवर्तित करते हैं क्योंकि जावा में चेक किए गए अपवादों का अत्यधिक उपयोग किया जाता है। एक उदाहरण जो मैं सोच सकता हूं, वह json.org से JSONException है, जो एक जांचा गया अपवाद है और ज्यादातर परेशान है - इसे अनियंत्रित किया जाना चाहिए, लेकिन डेवलपर ने इसके माध्यम से सोचा नहीं है।

वैसे, ज्यादातर समय अपवाद में कॉल करने वाले की रुचि सीधे तौर पर अपवाद से उबरने की क्षमता से होती है, लेकिन ऐसा हमेशा नहीं होता है।


13

यहाँ आपकी जाँच / अनियंत्रित दुविधा का एक बहुत ही सरल समाधान है।

नियम 1: कोड निष्पादित होने से पहले एक परीक्षण योग्य स्थिति के रूप में एक अनियंत्रित अपवाद के बारे में सोचें। उदाहरण के लिए…

x.doSomething(); // the code throws a NullPointerException

जहां x शून्य है ... कोड संभवतः निम्नलिखित होना चाहिए ...

if (x==null)
{
    //do something below to make sure when x.doSomething() is executed, it won’t throw a NullPointerException.
    x = new X();
}
x.doSomething();

नियम 2: एक जाँच की गई अपवाद के रूप में एक अन-परीक्षणीय स्थिति के बारे में सोचें जो कोड निष्पादित करते समय हो सकती है।

Socket s = new Socket(“google.com”, 80);
InputStream in = s.getInputStream();
OutputStream out = s.getOutputStream();

… ऊपर के उदाहरण में, DNS सर्वर डाउन होने के कारण URL (google.com) अनुपलब्ध हो सकता है। यहां तक ​​कि तत्काल DNS सर्वर काम कर रहा था और 'google.com' नाम को एक IP पते पर हल किया गया था, अगर कनेक्शन google.com से किया जाता है, तो कभी भी, नेटवर्क नीचे जा सकता है। आप बस धाराओं को पढ़ने और लिखने से पहले हर समय नेटवर्क का परीक्षण नहीं कर सकते।

ऐसे समय होते हैं जब कोड को निष्पादित करना चाहिए इससे पहले कि हम जान सकें कि क्या कोई समस्या है। चेक कोड एक्सेप्शन के माध्यम से इन परिस्थितियों को संभालने के लिए मजबूर करने के लिए डेवलपर्स को इस तरह से अपने कोड को लिखने के लिए मजबूर करके, मुझे इस अवधारणा का आविष्कार करने वाले जावा के निर्माता को अपनी टोपी टिप करनी होगी।

सामान्य तौर पर, जावा में लगभग सभी एपीआई ऊपर दिए गए 2 नियमों का पालन करते हैं। यदि आप किसी फ़ाइल में लिखने की कोशिश करते हैं, तो डिस्क लिखने को पूरा करने से पहले भर सकती है। यह संभव है कि अन्य प्रक्रियाओं के कारण डिस्क पूर्ण हो गई थी। इस स्थिति के लिए परीक्षण करने का कोई तरीका नहीं है। उन लोगों के लिए जो किसी भी समय हार्डवेयर के साथ बातचीत करते हैं, हार्डवेयर का उपयोग करना विफल हो सकता है, चेक किए गए अपवाद इस समस्या का एक सुरुचिपूर्ण समाधान प्रतीत होते हैं।

इसके लिए एक ग्रे क्षेत्र है। इस घटना में कि कई परीक्षणों की आवश्यकता होती है (एक मन बह रहा है अगर बहुत सारे && और;) के साथ बयान, अपवाद फेंक दिया गया एक CheckedException सिर्फ इसलिए कि यह बहुत दर्द हो रहा है सही हो जाएगा - आप बस इस समस्या को नहीं कह सकते एक प्रोग्रामिंग त्रुटि है। यदि 10 से कम परीक्षण हैं (जैसे 'अगर (x == null)'), तो प्रोग्रामर त्रुटि एक अनचेक किया जाना चाहिए।

भाषा दुभाषियों के साथ काम करते समय चीजें दिलचस्प हो जाती हैं। उपरोक्त नियमों के अनुसार, एक सिंटैक्स त्रुटि को एक जाँच या अनियंत्रित अपवाद माना जाना चाहिए? मैं तर्क दूंगा कि अगर भाषा की वाक्य रचना को निष्पादित करने से पहले परीक्षण किया जा सकता है, तो यह एक अनियंत्रित अपवाद होना चाहिए। यदि भाषा का परीक्षण नहीं किया जा सकता है - व्यक्तिगत कंप्यूटर पर असेंबली कोड कैसे चलता है, तो इसके समान ही सिंटैक्स त्रुटि एक जाँच अपवाद होनी चाहिए।

ऊपर दिए गए 2 नियम संभवतः आपकी 90% चिंता को दूर कर देंगे, जिसमें से चयन करना है। नियमों को सारांशित करने के लिए, इस पैटर्न का पालन करें ... 1) यदि कोड निष्पादित किया जा सकता है, तो इसे सही ढंग से चलाने के लिए निष्पादित करने से पहले परीक्षण किया जा सकता है और यदि अपवाद होता है - प्रोग्रामर त्रुटि उर्फ, अपवाद एक अनियंत्रित अपवाद होना चाहिए (RuntimeException का उपवर्ग) )। 2) यदि सही तरीके से चलाने के लिए निष्पादित किए जाने से पहले कोड को निष्पादित नहीं किया जा सकता है, तो अपवाद एक जाँच अपवाद (अपवाद का एक उपवर्ग) होना चाहिए।


9

आप इसे एक जाँच या अनियंत्रित अपवाद कह सकते हैं; हालाँकि, दोनों प्रकार के अपवाद को प्रोग्रामर द्वारा पकड़ा जा सकता है, इसलिए सबसे अच्छा उत्तर यह है: अपने सभी अपवादों को अनियंत्रित लिखें और उन्हें दस्तावेज करें। इस तरह से डेवलपर जो आपके एपीआई का उपयोग करता है वह चुन सकता है कि वह उस अपवाद को पकड़ना चाहता है या कुछ करना चाहता है। चेक किए गए अपवाद सभी के समय की पूरी बर्बादी हैं और यह आपके कोड को देखने के लिए एक चौंकाने वाला दुःस्वप्न बनाता है। उचित इकाई परीक्षण फिर किसी भी अपवाद को लाएगा जिसे आपको पकड़ना होगा और कुछ करना होगा।


1
+1 उल्लेख करने के लिए कि यूनिट परीक्षण समस्या को हल करने का एक बेहतर तरीका हो सकता है, अपवाद को हल करने का इरादा रखते हैं।
कीथ पिंसन

यूनिट परीक्षण के लिए +1। जाँच की गई / बिना किसी अपवाद के उपयोग से कोड की गुणवत्ता पर बहुत कम प्रभाव पड़ता है। तो तर्क है कि अगर कोई जाँच किए गए अपवादों का उपयोग करता है, तो इससे बेहतर कोड गुणवत्ता होगी, पूर्णतया संगीन तर्क है!
user1697575

7

चेक किया गया अपवाद: यदि ग्राहक एक अपवाद से उबर सकता है और जारी रखना चाहता है, तो चेक किए गए अपवाद का उपयोग करें।

अनियंत्रित अपवाद: यदि कोई ग्राहक अपवाद के बाद कोई काम नहीं कर सकता है, तो अनियंत्रित अपवाद बढ़ाएं।

उदाहरण: यदि आपसे विधि A () में अंकगणितीय ऑपरेशन करने की उम्मीद की जाती है और A () से आउटपुट के आधार पर आपको दूसरे ऑपरेशन के लिए जाना है। यदि आउटपुट पद्धति A () से शून्य है, जिसे आप रन टाइम के दौरान उम्मीद नहीं कर रहे हैं, तो आपको Null पॉइंटर अपवाद को फेंकने की उम्मीद है जो कि रन टाइम अपवाद है।

यहाँ देखें


2

मैं एक नियम के रूप में अनियंत्रित अपवादों के लिए प्राथमिकता से सहमत हूं, खासकर जब एक एपीआई डिजाइन करना। कॉलर हमेशा एक दस्तावेज, अनियंत्रित अपवाद को पकड़ने के लिए चुन सकता है। आप बस फोन करने वाले के लिए मजबूर करने की जरूरत नहीं है।

मुझे कार्यान्वयन अपवाद के रूप में निचले-स्तर पर जांचे गए अपवाद मिलते हैं। यह अक्सर एक निर्दिष्ट त्रुटि "रिटर्न कोड" का प्रबंधन करने की तुलना में नियंत्रण तंत्र के बेहतर प्रवाह की तरह लगता है। यह कभी-कभी निम्न स्तर के कोड परिवर्तन के लिए एक विचार के प्रभाव को देखने में भी मदद कर सकता है ... एक चेक किए गए अपवाद को डाउनस्ट्रीम घोषित करें और देखें कि किसे समायोजित करने की आवश्यकता है। यह अंतिम बिंदु लागू नहीं होता है अगर बहुत अधिक सामान्य हैं: पकड़ (अपवाद ई) या अपवाद फेंकता है जो आमतौर पर वैसे भी बहुत अच्छी तरह से सोचा नहीं जाता है।


2

यहाँ मैं कई वर्षों के विकास के अनुभव के बाद अपनी राय साझा करना चाहता हूँ:

  1. अपवाद की जाँच की। यह व्यावसायिक उपयोग के मामले या कॉल प्रवाह का एक हिस्सा है, यह एप्लिकेशन लॉजिक का एक हिस्सा है जिसकी हम अपेक्षा करते हैं या अपेक्षा नहीं करते हैं। उदाहरण के लिए अस्वीकार किए गए कनेक्शन, स्थिति संतुष्ट नहीं है आदि। हमें इसे संभालने और निर्देशों के साथ उपयोगकर्ता को संबंधित संदेश दिखाने की आवश्यकता है कि क्या हुआ और आगे क्या करना है (बाद में फिर से प्रयास करें आदि)। मैं आमतौर पर इसे पोस्ट-प्रोसेसिंग अपवाद या "उपयोगकर्ता" अपवाद कहता हूं।

  2. अनियंत्रित अपवाद। यह प्रोग्रामिंग अपवाद का एक हिस्सा है, सॉफ्टवेयर कोड प्रोग्रामिंग (बग, दोष) में कुछ गलती है और एक तरह से दर्शाती है कि प्रोग्रामर को कैसे प्रलेखन के रूप में एपीआई का उपयोग करना चाहिए। यदि कोई बाहरी परिवाद / ढांचा डॉक्टर कहता है कि यह कुछ सीमा और गैर अशक्त में डेटा प्राप्त करने की अपेक्षा करता है, क्योंकि NPE या IllegalArgumentException को फेंक दिया जाएगा, प्रोग्रामर को यह अपेक्षा करनी चाहिए और दस्तावेज़ के अनुसार एपीआई का सही उपयोग करें। अन्यथा अपवाद फेंक दिया जाएगा। मैं आमतौर पर इसे पूर्व-प्रसंस्करण अपवाद या "सत्यापन" अपवाद कहता हूं।

दर्शकों को लक्ष्य करके। अब आइए लक्ष्य दर्शकों या लोगों के समूह के बारे में बात करें, जो अपवादों को डिजाइन किए गए हैं (मेरी राय के अनुसार):

  1. अपवाद की जाँच की। लक्षित दर्शक उपयोगकर्ता / ग्राहक हैं।
  2. अनियंत्रित अपवाद। टारगेट ऑडियंस डेवलपर्स है। दूसरे शब्दों में अनियंत्रित अपवाद केवल डेवलपर्स के लिए डिज़ाइन किए गए हैं।

अनुप्रयोग विकास जीवनचक्र चरण द्वारा।

  1. चेक किए गए अपवाद को पूरे उत्पादन जीवनचक्र के दौरान सामान्य और अपेक्षित तंत्र के रूप में मौजूद रहने के लिए डिज़ाइन किया गया है, जो एक अनुप्रयोग असाधारण मामलों को संभालता है।
  2. अनियंत्रित अपवाद केवल अनुप्रयोग विकास / परीक्षण जीवनचक्र के दौरान मौजूद करने के लिए डिज़ाइन किया गया है, उन सभी को उस समय के दौरान ठीक किया जाना चाहिए और जब कोई अनुप्रयोग पहले से ही उत्पादन पर चल रहा हो तो उसे फेंक नहीं दिया जाना चाहिए।

आमतौर पर फ्रेमवर्क अनियंत्रित अपवाद (उदाहरण के लिए स्प्रिंग) का उपयोग करने का कारण यह है कि फ्रेमवर्क आपके आवेदन के व्यापारिक तर्क को निर्धारित नहीं कर सकता है, यह डेवलपर्स पर निर्भर है, फिर अपने तर्क को पकड़ने और डिजाइन करने के लिए।


2

हमें प्रोग्रामर त्रुटि है या नहीं इसके आधार पर इन दो प्रकार के अपवादों को अलग करना होगा।

  • यदि कोई त्रुटि प्रोग्रामर त्रुटि है, तो यह एक अनियंत्रित अपवाद होना चाहिए उदाहरण के लिए: SQLException / IOException / NullPointerException। ये अपवाद प्रोग्रामिंग त्रुटियाँ हैं। उन्हें प्रोग्रामर द्वारा नियंत्रित किया जाना चाहिए। JDBC API में, SQLException की जाँच अपवाद है, स्प्रिंग JDBCTemplate में, यह एक अनियंत्रित अपवाद है। Programmer स्प्रिंग का उपयोग करते समय SqlException के बारे में चिंता नहीं करता है।
  • यदि कोई त्रुटि प्रोग्रामर त्रुटि नहीं है और कारण बाहरी से आ रहा है, तो यह एक जाँच अपवाद होना चाहिए। उदाहरण के लिए: यदि फ़ाइल हटा दी जाती है या फ़ाइल अनुमति किसी अन्य व्यक्ति द्वारा बदल दी जाती है, तो उसे पुनर्प्राप्त किया जाना चाहिए।

FileNotFoundException सूक्ष्म अंतर को समझने के लिए अच्छा उदाहरण है। FileNotFoundException केस फाइल में नहीं मिलने पर फेंक दिया जाता है। इस अपवाद के दो कारण हैं। यदि फ़ाइल पथ डेवलपर द्वारा परिभाषित किया गया है या GUI के माध्यम से अंतिम उपयोगकर्ता से लिया जा रहा है तो यह एक अनियंत्रित अपवाद होना चाहिए। यदि फ़ाइल किसी और द्वारा हटा दी जाती है, तो यह एक जाँच अपवाद होना चाहिए।

चेक्ड एक्सेप्शन को दो तरह से हैंडल किया जा सकता है। ये ट्राइ-कैच का उपयोग कर रहे हैं या अपवाद का प्रचार कर रहे हैं। अपवाद के प्रसार के मामले में, कॉल स्टैक के सभी तरीकों को अपवाद हैंडलिंग के कारण कसकर युग्मित किया जाएगा । इसीलिए, हमें Checked Exception का उपयोग सावधानी से करना होगा।

यदि आप एक स्तरित उद्यम प्रणाली विकसित करते हैं, तो आपको फेंकने के लिए ज्यादातर अनियंत्रित अपवाद चुनना होगा, लेकिन इस मामले के लिए जाँच किए गए अपवाद का उपयोग करना न भूलें, जो आप कुछ भी नहीं कर सकते।


1

चेक किए गए अपवाद पुनर्प्राप्त करने योग्य मामलों के लिए उपयोगी होते हैं जहां आप कॉल करने वाले को जानकारी प्रदान करना चाहते हैं (अर्थात अपर्याप्त अनुमति, फ़ाइल नहीं मिली, आदि)।

अनियंत्रित अपवादों का उपयोग शायद ही कभी किया जाता है, यदि सभी, उपयोगकर्ता या प्रोग्रामर को गंभीर त्रुटियों या अनपेक्षित परिस्थितियों में रन-टाइम के दौरान सूचित करने के लिए। यदि आप कोड या पुस्तकालय लिख रहे हैं तो उन्हें फेंक न दें, जो कि दूसरों द्वारा उपयोग किया जाएगा, क्योंकि वे आपके सॉफ़्टवेयर से यह उम्मीद नहीं कर सकते हैं कि अनियंत्रित अपवाद फेंक दें क्योंकि कंपाइलर उन्हें पकड़ने या घोषित करने के लिए मजबूर नहीं करता है।


मैं आपके बयान से असहमत हूं "अनियंत्रित अपवाद शायद ही कभी उपयोग किए जाते हैं, यदि बिल्कुल" वास्तव में इसके विपरीत होना चाहिए! जब आप अपने एप्लिकेशन अपवादों को पदानुक्रम डिज़ाइन करते हैं तो डिफ़ॉल्ट रूप से अनियंत्रित एक्सप्रेशंस का उपयोग करें। डेवलपर्स को यह तय करने दें कि जब वे अपवाद को संभालना चाहते हैं (उदाहरण के लिए उन्हें पकड़ने के लिए मजबूर नहीं किया जाता है या फेंकता हुआ क्लॉज़ नहीं लगाया जाता है अगर वे नहीं जानते कि इसे कैसे संभालना है)।
user1697575

1

जब भी किसी अपवाद की उम्मीद कम होती है, और हम उसे पकड़ने के बाद भी आगे बढ़ सकते हैं, और हम उस अपवाद से बचने के लिए कुछ भी नहीं कर सकते हैं तब हम चेक किए गए अपवाद का उपयोग कर सकते हैं।

जब भी हम किसी विशेष अपवाद के होने पर कुछ सार्थक करना चाहते हैं और जब वह अपवाद अपेक्षित होता है, लेकिन निश्चित नहीं होता है, तो हम चेक किए गए अपवाद का उपयोग कर सकते हैं।

जब भी अपवाद अलग-अलग परतों में नेविगेट करते हैं, तो हमें इसे हर परत में पकड़ने की आवश्यकता नहीं होती है, उस स्थिति में, हम रनटाइम अपवाद या अनियंत्रित अपवाद के रूप में अपवाद को लपेट सकते हैं।

रनटाइम अपवाद का उपयोग तब किया जाता है जब अपवाद सबसे अधिक होने की संभावना है, आगे जाने का कोई रास्ता नहीं है और कुछ भी पुनर्प्राप्त करने योग्य नहीं हो सकता है। तो इस मामले में हम उस अपवाद के संबंध में सावधानी बरत सकते हैं। EX: NUllPointerException, ArrayOutofBoundsException। इनके होने की संभावना अधिक होती है। इस परिदृश्य में, हम इस तरह के अपवाद से बचने के लिए कोडिंग करते समय सावधानी बरत सकते हैं। नहीं तो हमें हर जगह ट्राई कैच ब्लॉक लिखना होगा।

अधिक सामान्य अपवाद अनियंत्रित किए जा सकते हैं, कम सामान्य जांच की जाती है।


1

मुझे लगता है कि हम कई प्रश्नों से छूट के बारे में सोच सकते हैं:

क्यों होता है वनवास? ऐसा होने पर हम क्या कर सकते हैं

गलती से, एक बग। जैसे शून्य वस्तु की एक विधि को कहा जाता है।

String name = null;
... // some logics
System.out.print(name.length()); // name is still null here

परीक्षण के दौरान इस तरह के अपवाद को तय किया जाना चाहिए। अन्यथा, यह उत्पादन को तोड़ता है, और आपको एक बहुत ही उच्च बग मिला है जिसे तुरंत ठीक करने की आवश्यकता है। इस तरह के अपवादों की जाँच की आवश्यकता नहीं है।

बाहरी इनपुट से, आप बाहरी सेवा के आउटपुट को नियंत्रित या भरोसा नहीं कर सकते।

String name = ExternalService.getName(); // return null
System.out.print(name.length());    // name is null here

यहां, आपको यह जांचने की आवश्यकता हो सकती है कि क्या नाम शून्य है यदि आप इसे जारी रखना चाहते हैं, तो यह शून्य है, अन्यथा, आप इसे अकेले जाने दे सकते हैं और यह यहां रुक जाएगा और कॉलर को रनटाइम अपवाद देगा। इस तरह के अपवादों की जाँच की आवश्यकता नहीं है।

बाहरी से रनटाइम अपवाद से, आप बाहरी सेवा को नियंत्रित या भरोसा नहीं कर सकते।

यहां, आपको बाहरी सेवा से सभी अपवादों को पकड़ने की आवश्यकता हो सकती है यदि आप ऐसा होने पर जारी रखना चाहते हैं, अन्यथा, आप इसे अकेले जाने दे सकते हैं और यह यहां रुक जाएगा और कॉलर को रनटाइम अपवाद देगा।

बाहरी अपवाद की जाँच करके, आप बाहरी सेवा पर नियंत्रण या भरोसा नहीं कर सकते।

यहां, आपको बाहरी सेवा से सभी अपवादों को पकड़ने की आवश्यकता हो सकती है यदि आप ऐसा होने पर जारी रखना चाहते हैं, अन्यथा, आप इसे अकेले जाने दे सकते हैं और यह यहां रुक जाएगा और कॉलर को रनटाइम अपवाद देगा।

इस मामले में, क्या हमें यह जानने की जरूरत है कि बाहरी सेवा में किस तरह का अपवाद हुआ? निर्भर करता है:

  1. यदि आप कुछ प्रकार के अपवादों को संभाल सकते हैं, तो आपको उन्हें पकड़ने और प्रक्रिया करने की आवश्यकता है। दूसरों के लिए, उन्हें बुलबुला।

  2. यदि आपको विशिष्ट निष्पादन के लिए उपयोगकर्ता की लॉग या प्रतिक्रिया की आवश्यकता है, तो आप उन्हें पकड़ सकते हैं। दूसरों के लिए, उन्हें बुलबुला।


0

मुझे लगता है कि अनुप्रयोग अपवाद की घोषणा करते समय इसे अनियंत्रित अपवाद यानी RuntimeException का उपवर्ग होना चाहिए। इसका कारण यह है कि ट्राइ-कैच और थ्रो डिक्लेरेशन के साथ आवेदन कोड को अव्यवस्थित नहीं किया जाएगा। यदि आपका एप्लिकेशन जावा एपि का उपयोग कर रहा है जो कि चेक किए गए अपवादों को फेंकता है जो कि किसी भी तरह से हैंडल करने की आवश्यकता है। अन्य मामलों के लिए, एप्लिकेशन अनियंत्रित अपवाद को फेंक सकता है। यदि एप्लिकेशन कॉलर को अभी भी अनियंत्रित अपवाद को संभालने की आवश्यकता है, तो यह किया जा सकता है।


-12

मेरे द्वारा उपयोग किया जाने वाला नियम है: कभी भी अनियंत्रित अपवादों का उपयोग न करें! (या जब आपको इसके आसपास कोई रास्ता दिखाई न दे)

अपनी लाइब्रेरी / एप्लिकेशन का उपयोग करके अपने पुस्तकालय या अंतिम-उपयोगकर्ता का उपयोग करने वाले डेवलपर के दृष्टिकोण से, यह वास्तव में एक एप्लिकेशन के साथ सामना करने के लिए बेकार हो जाता है जो बिना किसी अपवाद के क्रैश हो जाता है। और एक कैच पर गिनती-सभी अच्छा नहीं है।

इस तरह अंत उपयोगकर्ता को अभी भी पूरी तरह से गायब होने के बजाय एक त्रुटि संदेश के साथ प्रस्तुत किया जा सकता है।


1
आप यह नहीं समझाते हैं कि आपको क्या लगता है कि सबसे अनियंत्रित अपवादों के लिए कैच-ऑल गलत है।
मैथ्यू Flaschen

आपके गैर-तर्कपूर्ण जवाब से पूरी तरह असहमत: "कभी भी अनियंत्रित अपवादों का उपयोग न करें"
user1697575
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.