टी एल; डॉ
परिसर
- त्रुटि के अपरिवर्तनीय होने पर रनटाइम अपवाद को फेंक दिया जाना चाहिए: जब त्रुटि कोड में होती है, और बाहरी स्थिति पर निर्भर नहीं होती है (इसलिए, पुनर्प्राप्ति कोड को सही कर रही होगी)।
- कोड सही होने पर चेक किए गए अपवादों को फेंक दिया जाना चाहिए, लेकिन बाहरी स्थिति अपेक्षित नहीं है: कोई नेटवर्क कनेक्टिविटी, फ़ाइल नहीं मिली या भ्रष्ट है, आदि।
निष्कर्ष
यदि प्रोपेगेटिंग या इंटरफ़ेस कोड मानता है कि अंतर्निहित कार्यान्वयन बाहरी स्थिति पर निर्भर करता है, जब यह स्पष्ट रूप से नहीं होता है, तो हम रनटाइम अपवाद के रूप में एक अपवाद को हटा सकते हैं।
यह खंड इस विषय पर चर्चा करता है कि अपवादों को कब फेंका जाना चाहिए। यदि आप निष्कर्ष के लिए अधिक विस्तृत विवरण पढ़ना चाहते हैं, तो आप अगली क्षैतिज पट्टी पर जा सकते हैं।
रनटाइम अपवाद को फेंकना कब उचित है? आप रनटाइम अपवाद को फेंक देते हैं जब यह स्पष्ट होता है कि कोड गलत है, और कोड को संशोधित करके वह वसूली उपयुक्त है।
उदाहरण के लिए, निम्न के लिए रनटाइम अपवाद को फेंकना उचित है:
float nan = 1/0;
यह शून्य रनटाइम अपवाद द्वारा एक डिवीजन को फेंक देगा। यह उचित है क्योंकि कोड दोषपूर्ण है।
या उदाहरण के लिए, यहाँ HashMap
कंस्ट्रक्टर का एक हिस्सा है :
public HashMap(int initialCapacity, float loadFactor) {
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal initial capacity: " + initialCapacity);
if (initialCapacity > MAXIMUM_CAPACITY)
initialCapacity = MAXIMUM_CAPACITY;
if (loadFactor <= 0 || Float.isNaN(loadFactor))
throw new IllegalArgumentException("Illegal load factor: " +
loadFactor);
// more irrelevant code...
}
प्रारंभिक क्षमता या लोड फैक्टर को ठीक करने के लिए, यह उचित है कि आप यह सुनिश्चित करने के लिए कोड को संपादित करें कि सही मान पास किए जा रहे हैं। यह डिस्क के वर्तमान स्थिति पर कुछ दूर सर्वर पर निर्भर नहीं है। एक फ़ाइल, या एक अन्य कार्यक्रम। वह रचनाकार जिसे अवैध तर्कों के साथ बुलाया जा रहा है, कॉलिंग कोड की शुद्धता पर निर्भर करता है, यह एक गलत गणना है जो अमान्य पैरामीटर या अनुचित प्रवाह के कारण हुआ जो एक त्रुटि से चूक गया।
चेक किए गए अपवाद को फेंकना कब उचित है? जब कोड को बदले बिना समस्या ठीक हो जाए तो आप एक जाँच अपवाद को फेंक देते हैं । या इसे अलग-अलग शब्दों में रखने के लिए, आप त्रुटि की स्थिति से संबंधित अपवाद को एक चेक अपवाद को फेंक देते हैं जब कोड सही होता है।
अब "ठीक" शब्द यहां मुश्किल हो सकता है। इसका मतलब यह हो सकता है कि आपको लक्ष्य प्राप्त करने का एक और तरीका मिल जाए: उदाहरण के लिए, यदि सर्वर जवाब नहीं देता है तो आपको अगले सर्वर की कोशिश करनी चाहिए। यदि आपके मामले में उस तरह की रिकवरी संभव है, तो यह बहुत अच्छा है, लेकिन केवल यही रिकवरी का मतलब नहीं है - रिकवरी केवल उपयोगकर्ता को एक त्रुटि संवाद प्रदर्शित कर सकता है जो बताता है कि क्या हुआ, या यदि वह एक सर्वर एप्लिकेशन है तो यह हो सकता है व्यवस्थापक को एक ईमेल भेजना, या यहां तक कि त्रुटि को उचित और संक्षिप्त रूप से लॉग करना।
आइए उस उदाहरण को लेते हैं जिसका उल्लेख mrmuggles के उत्तर में किया गया था:
public void dataAccessCode(){
try{
..some code that throws SQLException
}catch(SQLException ex){
throw new RuntimeException(ex);
}
}
चेक किए गए अपवाद को संभालने का यह सही तरीका नहीं है। इस विधि के दायरे में अपवाद को संभालने के लिए मात्र अक्षमता का मतलब यह नहीं है कि ऐप को क्रैश कर दिया जाना चाहिए। इसके बजाय, इसे इस तरह उच्च दायरे में प्रचारित करना उचित है:
public Data dataAccessCode() throws SQLException {
// some code that communicates with the database
}
जो कॉलर द्वारा वसूली की संभावना के लिए अनुमति देता है:
public void loadDataAndShowUi() {
try {
Data data = dataAccessCode();
showUiForData(data);
} catch(SQLException e) {
// Recover by showing an error alert dialog
showCantLoadDataErrorDialog();
}
}
चेक किए गए अपवाद एक स्थैतिक-विश्लेषण उपकरण हैं, वे एक प्रोग्रामर के लिए यह स्पष्ट करते हैं कि एक निश्चित कॉल में क्या गलत हो सकता है बिना कार्यान्वयन को सीखने या परीक्षण और त्रुटि प्रक्रिया से गुजरने की आवश्यकता के बिना। इससे यह सुनिश्चित करना आसान हो जाता है कि त्रुटि प्रवाह के किसी भी हिस्से को नजरअंदाज नहीं किया जाएगा। रनटाइम अपवाद के रूप में चेक किए गए अपवाद को रिथ्रो करना इस श्रम-बचत स्थैतिक विश्लेषण सुविधा के खिलाफ काम कर रहा है।
यह भी ध्यान देने योग्य है कि कॉलिंग लेयर में चीजों की grander योजना का बेहतर संदर्भ है जैसा कि ऊपर दिखाया गया है। इसके कई कारण हो सकते हैं dataAccessCode
, जिन्हें कॉल किया जाएगा, कॉल का विशिष्ट कारण केवल कॉल करने वाले को दिखाई देता है - इस प्रकार यह विफलता पर सही रिकवरी पर बेहतर निर्णय लेने में सक्षम है।
अब जब हमें यह अंतर स्पष्ट हो गया है, तो जब हम रनटाइम अपवाद के रूप में चेक किए गए अपवाद को फिर से हटाना चाहते हैं, तो हम घटा सकते हैं।
उपरोक्त को देखते हुए, RuntimeException के रूप में चेक किए गए अपवाद को पुनर्विचार करना कब उचित है? जब कोड आप बाहरी राज्य पर निर्भरता का उपयोग कर रहे हैं, लेकिन आप स्पष्ट रूप से दावा कर सकते हैं कि यह बाहरी राज्य पर निर्भर नहीं करता है।
निम्नलिखित को धयान मे रखते हुए:
StringReader sr = new StringReader("{\"test\":\"test\"}");
try {
doesSomethingWithReader(sr); // calls #read, so propagates IOException
} catch (IOException e) {
throw new IllegalStateException(e);
}
इस उदाहरण में, कोड प्रचारित कर रहा है IOException
क्योंकि एपीआई का Reader
बाहरी राज्य तक पहुँचने के लिए डिज़ाइन किया गया है, हालाँकि हम जानते हैं कि StringReader
कार्यान्वयन बाहरी राज्य तक नहीं पहुँचता है। इस दायरे में, जहां हम निश्चित रूप से जोर दे सकते हैं कि कॉल में शामिल पुर्जे IO या किसी अन्य बाहरी स्थिति तक नहीं पहुंचते हैं, हम आश्चर्यजनक रूप से अपवाद के रूप में एक अपवाद के रूप में इस अपवाद को हटा सकते हैं जो हमारे कार्यान्वयन से अनजान हैं (और संभवतः यह मानते हुए कि IO-accessing code a IOException
) फेंक देगा ।
सख्ती से बाहरी राज्य निर्भर अपवाद रखने के लिए कारण की जाँच की है कि वे गैर नियतात्मक (तर्क निर्भर अपवाद है, जो जाहिर कोड का एक संस्करण के लिए हर बार reproduced किया जाएगा के विपरीत) कर रहे हैं। उदाहरण के लिए, यदि आप 0 से विभाजित करने का प्रयास करते हैं, तो आप हमेशा एक अपवाद का उत्पादन करेंगे। यदि आप 0 से विभाजित नहीं करते हैं, तो आप कभी भी अपवाद का उत्पादन नहीं करेंगे, और आपको उस अपवाद मामले को संभालना नहीं होगा, क्योंकि ऐसा कभी नहीं होगा। किसी फ़ाइल तक पहुँचने के मामले में, हालाँकि, एक बार सफल होने का मतलब यह नहीं है कि आप अगली बार सफल होंगे - उपयोगकर्ता ने अनुमतियाँ बदल दी होंगी, हो सकता है कि किसी अन्य प्रक्रिया ने उसे हटा दिया या संशोधित कर दिया हो। इसलिए आपको हमेशा उस असाधारण मामले को संभालना होगा, या आपके पास एक बग होने की संभावना है।