क्या यह पकड़ने के लिए एक बुरा अभ्यास है Throwable?
उदाहरण के लिए कुछ इस तरह से:
try {
// Some code
} catch(Throwable e) {
// handle the exception
}
क्या यह एक बुरा अभ्यास है या हमें यथासंभव विशिष्ट होना चाहिए?
क्या यह पकड़ने के लिए एक बुरा अभ्यास है Throwable?
उदाहरण के लिए कुछ इस तरह से:
try {
// Some code
} catch(Throwable e) {
// handle the exception
}
क्या यह एक बुरा अभ्यास है या हमें यथासंभव विशिष्ट होना चाहिए?
जवाबों:
आपको यथासंभव विशिष्ट होने की आवश्यकता है। अन्यथा अप्रत्याशित कीड़े इस तरह से दूर हो सकते हैं।
इसके अलावा, Throwableकवर के Errorरूप में अच्छी तरह से और आमतौर पर वापसी का कोई मतलब नहीं है । आप इसे पकड़ना / संभालना नहीं चाहते हैं, आप चाहते हैं कि आपका कार्यक्रम तुरंत मर जाए ताकि आप इसे ठीक से ठीक कर सकें।
यह विचार अच्छा नहीं है। वास्तव में, यहां तक कि पकड़ना Exceptionआमतौर पर एक बुरा विचार है। आइए एक उदाहरण पर विचार करें:
try {
inputNumber = NumberFormat.getInstance().formatNumber( getUserInput() );
} catch(Throwable e) {
inputNumber = 10; //Default, user did not enter valid number
}
अब, मान लें कि getUserInput () थोड़ी देर के लिए ब्लॉक हो जाता है, और दूसरा धागा आपके थ्रेड को सबसे खराब तरीके से रोकता है (इसे थ्रेड.स्टॉप () कहता है)। आपका कैच ब्लॉक ThreadDeathएरर पकड़ लेगा । यह सुपर खराब है। उस अपवाद को पकड़ने के बाद आपके कोड का व्यवहार काफी हद तक अपरिभाषित है।
अपवाद को पकड़ने के साथ एक समान समस्या होती है। हो सकता है getUserInput()कि एक InterruptException, या एक अनुमति के कारण विफल रहा है जबकि परिणाम, या अन्य विफलताओं के सभी प्रकार के लॉग इन करने की कोशिश कर रहे अपवाद से इनकार कर दिया। आपके पास कोई विचार नहीं है कि क्या गलत हुआ, क्योंकि इसके कारण, आपको यह भी पता नहीं है कि समस्या को कैसे ठीक किया जाए।
आपके पास तीन बेहतर विकल्प हैं:
1 - सटीक अपवाद को पकड़ो जो आप जानते हैं कि कैसे संभालना है:
try {
inputNumber = NumberFormat.getInstance().formatNumber( getUserInput() );
} catch(ParseException e) {
inputNumber = 10; //Default, user did not enter valid number
}
2 - आपके द्वारा चलाए जा रहे किसी भी अपवाद को रोकें और संभालना नहीं जानते:
try {
doSomethingMysterious();
} catch(Exception e) {
log.error("Oh man, something bad and mysterious happened",e);
throw e;
}
3 - अंत में ब्लॉक का उपयोग करें ताकि आपको पुनर्विचार करने के लिए याद न करना पड़े:
Resources r = null;
try {
r = allocateSomeResources();
doSomething(r);
} finally {
if(r!=null) cleanUpResources(r);
}
throw new Exception("Some additional info, eg. userId " + userId, e);। यह 10 कारणों के साथ एक अच्छे अपवाद में लॉग इन किया जाएगा।
यह भी ध्यान रखें कि जब आप पकड़ते हैं Throwable, तो आप भी पकड़ सकते हैं InterruptedExceptionजिसके लिए एक विशेष उपचार की आवश्यकता होती है। अधिक जानकारी के लिए InterruptedException से निपटना देखें ।
यदि आप केवल अनियंत्रित अपवादों को पकड़ना चाहते हैं, तो आप इस पैटर्न पर भी विचार कर सकते हैं
try {
...
} catch (RuntimeException exception) {
//do something
} catch (Error error) {
//do something
}
इस तरह, जब आप अपने कोड को संशोधित करते हैं और एक विधि कॉल जोड़ते हैं जो एक चेक अपवाद को फेंक सकता है, तो कंपाइलर आपको उसकी याद दिलाएगा और फिर आप तय कर सकते हैं कि इस मामले के लिए क्या करना है।
त्रुटि वर्ग के javadoc से सीधे (जो इन्हें न पकड़ने की सलाह देता है):
* An <code>Error</code> is a subclass of <code>Throwable</code>
* that indicates serious problems that a reasonable application
* should not try to catch. Most such errors are abnormal conditions.
* The <code>ThreadDeath</code> error, though a "normal" condition,
* is also a subclass of <code>Error</code> because most applications
* should not try to catch it.
* A method is not required to declare in its <code>throws</code>
* clause any subclasses of <code>Error</code> that might be thrown
* during the execution of the method but not caught, since these
* errors are abnormal conditions that should never occur.
*
* @author Frank Yellin
* @version %I%, %G%
* @see java.lang.ThreadDeath
* @since JDK1.0
यह एक बुरा अभ्यास नहीं है यदि आप बिल्कुल एक विधि से बाहर एक अपवाद बुलबुला नहीं हो सकता है।
यदि आप वास्तव में अपवाद को नहीं संभाल सकते हैं तो यह एक बुरा अभ्यास है। बेहतर तरीके से "थ्रो" को जोड़ने के लिए सिर्फ पकड़ने और फिर से फेंकने की तुलना में विधि हस्ताक्षर में इसे RuntimeException और पुनः-फेंक में लपेटें।
Throwableउदाहरणों को संभालने के लिए बिल्कुल वैध मामले हैं - उदाहरण के लिए कस्टम अपवाद लॉगिंग।
थ्रोबेबल को पकड़ना कभी-कभी आवश्यक होता है यदि आप पुस्तकालयों का उपयोग कर रहे हैं जो त्रुटियों को अति उत्साह से फेंकते हैं, अन्यथा आपका पुस्तकालय आपके आवेदन को मार सकता है।
हालाँकि, इन परिस्थितियों में सबसे अच्छा होगा कि सभी थ्रोबेबल्स की बजाय केवल लाइब्रेरी द्वारा फेंकी गई विशिष्ट त्रुटियों को निर्दिष्ट करें।
थ्रोएबल सभी वर्गों के लिए आधार वर्ग है जिसे फेंका जा सकता है (केवल अपवाद नहीं)। अगर आप आउटऑफ़मेरीऑरर या कर्नेलएर्रर को पकड़ते हैं तो बहुत कम आप कर सकते हैं (देखें कि java.lang.Error कब पकड़ना है? )
अपवादों को पकड़ना पर्याप्त होना चाहिए।
यह आपके तर्क पर निर्भर करता है या आपके विकल्पों / संभावनाओं के लिए अधिक विशिष्ट होता है। यदि कोई विशिष्ट अपवाद है जो आप संभवतः सार्थक तरीके से प्रतिक्रिया कर सकते हैं, तो आप इसे पहले पकड़ सकते हैं और ऐसा कर सकते हैं।
यदि ऐसा नहीं है और आप सुनिश्चित हैं कि आप सभी अपवादों और त्रुटियों के लिए एक ही काम करेंगे (उदाहरण के लिए एक त्रुटि-संदेश के साथ बाहर निकलें), तो यह फेंकने योग्य को पकड़ने के लिए समस्या नहीं है।
आमतौर पर पहला मामला पकड़ में आता है और आप फेंकने योग्य नहीं होते। लेकिन अभी भी बहुत सारे मामले हैं जहां इसे पकड़ना ठीक काम करता है।
यद्यपि यह एक बहुत ही खराब प्रथा के रूप में वर्णित है, आप कभी-कभी दुर्लभ मामलों को पा सकते हैं कि यह न केवल उपयोगी है, बल्कि अनिवार्य भी है। यहाँ दो उदाहरण हैं।
एक वेब एप्लिकेशन में जहां आपको उपयोगकर्ता को एक अर्थ पूर्ण त्रुटि पृष्ठ दिखाना होगा। यह कोड सुनिश्चित करता है कि ऐसा होता है क्योंकि यह try/catchआपके सभी अनुरोध हैंडेलर्स (सर्वलेट्स, स्ट्रट्स एक्शन या किसी भी कंट्रोलर ...) के आसपास एक बड़ा है ।
try{
//run the code which handles user request.
}catch(Throwable ex){
LOG.error("Exception was thrown: {}", ex);
//redirect request to a error page.
}
}
एक अन्य उदाहरण के रूप में, विचार करें कि आपके पास एक सेवा वर्ग है जो फंड ट्रांसफर व्यवसाय का कार्य करता है। TransferReceiptयदि स्थानांतरण किया जाता है या NULLयदि यह नहीं हो सका तो यह विधि वापस आती है ।
String FoundtransferService.doTransfer( fundtransferVO);
अब इमेजिंग से आपको Listउपयोगकर्ता से फंड ट्रांसफर की सुविधा मिलती है और आपको उन सभी को करने के लिए उपरोक्त सेवा का उपयोग करना होगा।
for(FundTransferVO fundTransferVO : fundTransferVOList){
FoundtransferService.doTransfer( foundtransferVO);
}
लेकिन अगर कोई अपवाद होता है तो क्या होगा ? आपको रुकना नहीं चाहिए, क्योंकि एक हस्तांतरण सफल हो सकता है और एक नहीं हो सकता है, आपको सभी उपयोगकर्ता के माध्यम से चलते रहना चाहिए List, और प्रत्येक हस्तांतरण के लिए परिणाम दिखाना चाहिए । इसलिए आप इस कोड को समाप्त करें।
for(FundTransferVO fundTransferVO : fundTransferVOList){
FoundtransferService.doTransfer( foundtransferVO);
}catch(Throwable ex){
LOG.error("The transfer for {} failed due the error {}", foundtransferVO, ex);
}
}
आप यह देखने के लिए बहुत सारे ओपन सोर्स प्रोजेक्ट ब्राउज़ कर सकते हैं कि throwableयह वास्तव में कैश्ड और हैंडल है। उदाहरण के लिए यहाँ एक खोज है tomcat, struts2और primefaces:
https://github.com/apache/tomcat/search?utf8=%E2%9C%93&q=catch%28Throwable https://github.com/apache/struts/search?utf8-%E2%9C%93&q=catch % 28Throwable https://github.com/primefaces/primefaces/search?utf8=%E2%9C%93&q=catch%28Throwable
throwable
सवाल थोड़ा अस्पष्ट है; क्या आप पूछ रहे हैं "क्या यह पकड़ने के लिए ठीक है Throwable", या "क्या इसे पकड़ना ठीक है Throwableऔर कुछ नहीं करना है"? यहाँ कई लोगों ने उत्तर दिया, लेकिन यह एक पक्ष है; समय के 99% आप नहीं करना चाहिए "उपभोग" या अपवाद को छोड़ दे, आप को पकड़ने रहे हैं कि क्या Throwableया IOExceptionया जो कुछ भी।
यदि आप अपवाद का प्रचार करते हैं, तो उत्तर (जैसे कई प्रश्नों के उत्तर) "यह निर्भर करता है" है। यह इस बात पर निर्भर करता है कि आप अपवाद के साथ क्या कर रहे हैं — आप इसे क्यों पकड़ रहे हैं।
यदि आप Throwableकोई त्रुटि चाहते हैं तो इसका एक अच्छा उदाहरण है कि किसी प्रकार की सफाई प्रदान करना । उदाहरण के लिए, JDBC में, यदि लेन-देन के दौरान कोई त्रुटि होती है, तो आप लेन-देन वापस करना चाहेंगे:
try {
…
} catch(final Throwable throwable) {
connection.rollback();
throw throwable;
}
ध्यान दें कि अपवाद को खारिज नहीं किया गया है, लेकिन प्रचारित किया गया है।
लेकिन एक सामान्य नीति के रूप में, पकड़ना Throwableक्योंकि आपके पास कोई कारण नहीं है और यह देखने के लिए बहुत आलसी हैं कि कौन से विशिष्ट अपवादों को फेंका जा रहा है, खराब रूप और एक बुरा विचार है।
आम तौर पर बोलते हुए आप कैच से बचना चाहते हैं Errorलेकिन मैं दो विशिष्ट मामलों के बारे में सोच सकता हूं जहां ऐसा करना उचित है:
AssertionError जो अन्यथा हानिरहित है।अगर हम फेंकने योग्य का उपयोग करते हैं , तो यह त्रुटि को भी कवर करता है और यही है।
उदाहरण।
public class ExceptionTest {
/**
* @param args
*/
public static void m1() {
int i = 10;
int j = 0;
try {
int k = i / j;
System.out.println(k);
} catch (Throwable th) {
th.printStackTrace();
}
}
public static void main(String[] args) {
m1();
}
}
आउटपुट:
java.lang.ArithmeticException: / by zero
at com.infy.test.ExceptionTest.m1(ExceptionTest.java:12)
at com.infy.test.ExceptionTest.main(ExceptionTest.java:25)
थ्रोबल सभी त्रुटियों और उत्तेजनाओं का सुपरक्लास है। यदि आप थ्रोबेबल को कैच क्लॉज में उपयोग करते हैं, तो यह न केवल सभी अपवादों को पकड़ लेगा, बल्कि सभी त्रुटियों को भी पकड़ लेगा। गंभीर समस्याओं को इंगित करने के लिए जेवीएम द्वारा त्रुटियां डाली जाती हैं जो एक आवेदन द्वारा नियंत्रित नहीं की जाती हैं। इसके लिए विशिष्ट उदाहरण OutOfMemoryError या StackOverflowError हैं। दोनों उन स्थितियों के कारण होते हैं जो एप्लिकेशन के नियंत्रण से बाहर हैं और उन्हें नियंत्रित नहीं किया जा सकता है। इसलिए आपको थ्रोबेबल्स को तब तक नहीं पकड़ना चाहिए जब तक कि आपका पूरा भरोसा न हो कि यह केवल थ्रोबल के अंदर एक अपवाद होगा।
हालांकि थ्रोएबल को पकड़ने के लिए आम तौर पर बुरा अभ्यास होता है (जैसा कि इस सवाल पर कई उत्तरों द्वारा स्पष्ट किया गया है), ऐसे परिदृश्य जहां पकड़ने Throwableउपयोगी है, काफी सामान्य हैं। मुझे एक ऐसे मामले की व्याख्या करें जो मैं अपनी नौकरी में उपयोग करता हूं, एक सरलीकृत उदाहरण के साथ।
एक विधि पर विचार करें जो दो संख्याओं को जोड़ती है, और सफल जोड़ के बाद, यह कुछ लोगों को ईमेल अलर्ट भेजती है। मान लें कि वापस लौटा नंबर महत्वपूर्ण है और कॉलिंग विधि द्वारा उपयोग किया जाता है।
public Integer addNumbers(Integer a, Integer b) {
Integer c = a + b; //This will throw a NullPointerException if either
//a or b are set to a null value by the
//calling method
successfulAdditionAlert(c);
return c;
}
private void successfulAdditionAlert(Integer c) {
try {
//Code here to read configurations and send email alerts.
} catch (Throwable e) {
//Code to log any exception that occurs during email dispatch
}
}
ईमेल अलर्ट भेजने का कोड बहुत सारे सिस्टम कॉन्फ़िगरेशन को पढ़ता है और इसलिए, कोड के उस ब्लॉक से अलग-अलग अपवाद हो सकते हैं। लेकिन हम यह नहीं चाहते हैं कि अलर्ट प्रेषण के दौरान कोई भी अपवाद कॉलर पद्धति को प्रचारित करने के लिए है, क्योंकि यह विधि केवल दो पूर्णांक मानों के योग से संबंधित है जो इसे प्रदान करता है। इसलिए, ईमेल अलर्ट भेजने का कोड एक try-catchब्लॉक में रखा जाता है , जहां Throwableपकड़ा जाता है और किसी भी अपवाद को केवल लॉग किया जाता है, जिससे बाकी का प्रवाह जारी रहता है।
Exceptionहर तरह से पकड़ो , लेकिन नहीं Throwable।