2013-09-08 16 views
27

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

Method A will call Method B and Method B will call some Method C and Method C will call Method D and Method E. 

की तरह कुछ तो वर्तमान में मैं क्या कर रहा हूँ है- मैं सभी तरीकों में अपवाद फेंक कर रहा हूँ और विधि एक में यह पकड़ने और फिर एक त्रुटि के रूप में प्रवेश करने है।

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

क्या कोई मुझे When to catch the Exception vs When to throw the Exceptions का विस्तृत उदाहरण दे सकता है ताकि मेरी अवधारणाओं को इस पर मंजूरी मिल सके? और मेरे मामले में, क्या मुझे अपवाद फेंकना चाहिए और फिर उसे मुख्य कॉलिंग विधि ए में पकड़ना चाहिए?

+2

आपको हमेशा उस स्तर को पकड़ना चाहिए जब स्थिति को संभालना संभव हो, जिसके परिणामस्वरूप अपवाद ठीक से हो ... – ppeterka

+0

यह एक या दूसरे का सवाल नहीं है। आप अपवादों को कुछ प्रसंस्करण कर सकते हैं और फिर उन्हें पुनर्स्थापित कर सकते हैं। आपको शायद कुछ ठोस उदाहरणों के साथ आना चाहिए जो आप सोच रहे हैं। यहां एक उदाहरण पोस्ट करें जैसा कि यहां अनुशंसित किया गया है: http://www.sscce.org/ – dcaswell

उत्तर

4

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

में विफल रहता है आप इसे कैसे संभालना चाहते हैं? शायद एक संवाद डालने से "क्षमा करें, सेवर/डीबी से कनेक्ट नहीं हो सकता" या जो भी हो। क्या विधि ए, बी, या सी है जिसने इस सर्वर/डीबी की जानकारी बनाई है (कहें, सेटिंग्स फ़ाइल पढ़कर या उपयोगकर्ता इनपुट मांगकर) और कनेक्शन की कोशिश की? यह शायद विधि है जो अपवाद को संभालना चाहिए। या उस विधि से कम से कम 1 दूर इसे संभालना चाहिए।

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

वेब ऐप में यह अलग हो सकता है।

कुछ बहुत कंकाल कोड, अधिकांश कक्षाएं मौजूद नहीं हैं, और मुझे यकीन नहीं है कि डीबी के लिए एक यूआरएल भी समझ में आता है, लेकिन आपको विचार मिलता है। अस्पष्ट स्विंगिश ...

/* gets called by an actionListener when user clicks a menu etc... */ 
public URL openTheDB() { 
    URL urlForTheDB = MyCoolDialogUtils.getMeAURL(URL somePreviousOneToFillInTheStart); 
    try { 
    verifyDBExists(urlForTheDB); 
    // this may call a bunch of deep nested calls that all can throw exceptions 
    // let them trickle up to here 

    // if it succeeded, return the URL 
    return urlForTheDB; 
    } 
    catch (NoDBExeption ndbe) { 
    String message = "Sorry, the DB does not exist at " + URL; 
    boolean tryAgain = MyCoolDialogUtils.error(message); 
    if (tryAgain) 
     return openTheDB(); 
    else 
     return null; // user said cancel... 
    } 
    catch (IOException joe) { 
    // maybe the network is down, aliens have landed 
    // create a reasonable message and show a dialog 
    } 

} 
37

जब आप इस विधि में हैं तो आपको अपवाद पकड़ना चाहिए जो जानता है कि क्या करना है।

उदाहरण के लिए, इस पल के लिए वास्तव में कैसे काम करता है, इस बारे में भूल जाएं, मान लें कि आप फ़ाइलों को खोलने और पढ़ने के लिए एक पुस्तकालय लिख रहे हैं।

तो तुम एक वर्ग का कहना है कि है

public class FileInputStream extends InputStream { 
    public FileInputStream(String filename) { } 
} 

अब, मान लीजिए कि फ़ाइल मौजूद नहीं है। आपको क्या करना चाहिये? यदि आप उत्तर के बारे में सोचने के लिए संघर्ष कर रहे हैं, ऐसा इसलिए है क्योंकि कोई नहीं है ... FileInputStream नहीं जानता कि उस समस्या के बारे में क्या करना है। तो यह श्रृंखला को फेंकता है, यानी:

public class FileInputStream extends InputStream { 
    public FileInputStream(String filename) throws FileNotFoundException { } 
} 

अब, किसी को अपनी लाइब्रेरी का उपयोग करने का कहना है।

public class Main { 
    public static void main(String... args) { 
     String filename = "foo.txt"; 
     try { 
      FileInputStream fs = new FileInputStream(filename); 

      // The rest of the code 
     } catch (FileNotFoundException e) { 
      System.err.println("Unable to find input file: " + filename); 
      System.err.println("Terminating..."); 
      System.exit(3); 
     } 
    } 
} 

यहाँ, प्रोग्रामर जानता है कि क्या करना है, ताकि वे अपवाद को पकड़ने और इसे संभाल: वे कोड है कि इस तरह दिखता है हो सकता है।

+0

-1 stderr को एक संदेश प्रिंट करना जो फ़ाइल नाम का संदर्भ भी नहीं देता है, उसके बाद जेवीएम के कठिन बाहर निकलने के बाद, अपवाद को "संभालना" मुश्किल से है । कृपया अपना कोड सुधारें। (मुझे पता है कि यह सिर्फ एक तेज उदाहरण है, लेकिन आप बेहतर कर सकते हैं ...) – user949300

+11

@ user949300 यह एक [एसएससीईसी] (http://sscce.org) है, इसे दूसरे के साथ छेड़छाड़ करने के बजाए यह एक साधारण उदाहरण होना चाहिए सामान। आप 'फ़ाइल नाम' के बारे में एक अच्छा मुद्दा बनाते हैं, हालांकि, मैंने तय किया है। – durron597

+1

@ user949300 यह भी ध्यान देता है कि यह 'मुख्य' विधि में है, वहां वास्तव में बहुत कुछ नहीं है। जाहिर है आप कोड – durron597

1

जब आप कुछ विफलताओं की विधि के कॉलर को सूचित करना चाहते हैं तो आप आम तौर पर एक अपवाद फेंकता है।

, उदा, अमान्य उपयोगकर्ता इनपुट, डेटाबेस समस्याओं, नेटवर्क की त्रुटियों, अनुपस्थित फ़ाइलों

3

आप न्यूनतम संभव स्तर पर अपवाद प्रबंधित करें। यदि विधि अपवाद को सही तरीके से संभाल नहीं सकती है तो आपको इसे फेंकना चाहिए।

  • पकड़ आप विधि है जो संसाधन से कनेक्ट होता है, तो
  • फेंक (जैसे फ़ाइल/नेटवर्क खुलता है) एक सामान्य नियम के रूप में अगर वर्ग पदानुक्रम में उच्च
0

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

उदाहरण के लिए, आप कोड है कि एक को बचाने फ़ाइल से एक को जोड़ने खिलाड़ी के बारे में जानकारी पढ़ता है और अपने आई/ओ तरीकों में से एक में लिख रहे हैं, तो एक IOException फेंकता है, तो आप उस अपवाद और कोड कि load लागू फेंकने के लिए चाहते हो जाएगा विधि उस अपवाद को पकड़ना चाहती है और तदनुसार इसे संभालना चाहती है (जैसे खिलाड़ी को डिस्कनेक्ट करना, या क्लाइंट को प्रतिक्रिया भेजना आदि)। load विधि में अपवाद को संभालने का कारण यह नहीं है क्योंकि विधि में, आप अर्थपूर्ण रूप से अपवाद को संभाल नहीं सकते हैं, इसलिए आप कॉलर को अपवाद का प्रतिनिधि उम्मीद करते हैं कि वे इसे संभाल सकें।

3

मैं एक पैटर्न साझा करूंगा जिसने मेरे बेकन को उत्पादन वातावरण या दो में सहेजा है।

प्रेरणा

मेरा उद्देश्य यह सुनिश्चित करना है कि गरीब दोस्त (शायद मुझे) जो आधी रात को में एक sev1 समर्थन टिकट को हल करने की कोशिश कर रहा है, का एक अच्छा पदानुक्रम हो जाता है करने के लिए त्रुटियों 'की वजह से से' कोड के साथ छेड़छाड़ किए बिना, आईडी के रूप में डेटा के साथ पूरा करें।

विधि

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

throw new RuntimeException(checked,"Could not retrieve contact " + id); 

होने वाली इस दृष्टिकोण के साथ से 'डबल प्रवेश' को रोकने के लिए आपकी जीयूआई का कोई अव्यवस्था है या डेटाबेस संबंधी अपवादों के लिए 'फेंकता' घोषित करके व्यवसाय स्तर की विधि हस्ताक्षर।

एक यह कैसे रियल लाइफ में काम करता है का उदाहरण:

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

त्रुटि लॉग के प्रकार का एक उदाहरण मैं प्राप्त करना चाहता हूं।

Log message: Flagging policy 1234 for manual intervention due to error:

From Stack Trace: Error Renewing Policy 1234. Rolling back the transaction ... This catch would also cover errors such as save errors, or generation of a letter.

From Stack Trace: Caused by: Error Rating Policy 1234 ... This catch would pickup errors retrieving many other objects, and algorithm errors such as NPE etc...

From Stack Trace: Caused by: Error Retrieving Rating Area 73932 ...

From Stack Trace: Caused by: JPA: unexpected null in field 'postcode'

5

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

एक फ़ंक्शन काम की एक इकाई है, और असफलताओं को त्रुटियों के रूप में देखा जाना चाहिए या अन्यथा कार्यों पर उनके प्रभाव के आधार पर देखा जाना चाहिए। एक समारोह के भीतर, एक विफलता एक त्रुटि है यदि और केवल यदि वह अपने कॉल प्राप्त करने वाला का पूर्व शर्त के किसी भी बैठक, च की खुद postconditionsमें से किसी को प्राप्त करने, या किसी भी अपरिवर्तनीय रीस्ताब्लिशिंग से से बचाता है कि एफ बनाए रखने के लिए ज़िम्मेदारी साझा करता है।

त्रुटियों की तीन अलग अलग प्रकार के होते हैं:

  • एक शर्त है कि एक और समारोह है कि बुलाया जाना चाहिए की एक पूर्व शर्त है (जैसे, एक पैरामीटर प्रतिबंध) से मिलने से समारोह रोकता है,
  • ऐसी स्थिति जो फ़ंक्शन को अपने स्वयं के पोस्टकंडिशन में से एक स्थापित करने से रोकती है (उदाहरण के लिए, वैध वापसी मान का उत्पादन एक पोस्टकंडिशन है); और
  • ऐसी स्थिति जो फ़ंक्शन को एक आविष्कार को फिर से स्थापित करने से रोकती है जो इसे बनाए रखने के लिए ज़िम्मेदार है। यह एक विशेष प्रकार का पोस्टकंडिशन है जो विशेष रूप से सदस्य कार्यों पर लागू होता है। प्रत्येक गैर-निजी सदस्य कार्य का एक आवश्यक पोस्टकंडिशन यह है कि इसे अपने वर्ग के आविष्कारों को फिर से स्थापित करना होगा।

कोई अन्य शर्त नहीं एक त्रुटि है और एक त्रुटि के रूप में रिपोर्ट नहीं किया जाना चाहिए।

एक त्रुटि की रिपोर्ट करें जहां कोई फ़ंक्शन किसी त्रुटि का पता लगाता है जो वह स्वयं से निपट नहीं सकता है और जो इसे सामान्य या इच्छित संचालन के किसी भी रूप में जारी रखने से रोकता है।

उन स्थानों में त्रुटि को संभालें जिनके पास त्रुटि को संभालने के लिए पर्याप्त ज्ञान है, या अनुवाद नीति में परिभाषित सीमाओं को लागू करने के लिए, जैसे मुख्य या थ्रेड मेनलाइन।

संबंधित मुद्दे