क्या मैं एक ही पकड़ने वाले खंड में कई जावा अपवादों को पकड़ सकता हूं?


701

जावा में, मैं कुछ इस तरह करना चाहता हूं:

try {
    ...     
} catch (/* code to catch IllegalArgumentException, SecurityException, 
            IllegalAccessException, and NoSuchFieldException at the same time */) {
   someCode();
}

...के बजाय:

try {
    ...     
} catch (IllegalArgumentException e) {
    someCode();
} catch (SecurityException e) {
    someCode();
} catch (IllegalAccessException e) {
    someCode();
} catch (NoSuchFieldException e) {
    someCode();
}

क्या इसे करने का कोई तरीका है?

जवाबों:


1132

यह जावा 7 के बाद से संभव हुआ है । मल्टी-कैच ब्लॉक के लिए सिंटैक्स है:

try { 
  ...
} catch (IOException | SQLException ex) { 
  ...
}

हालांकि, याद रखें कि यदि सभी अपवाद समान श्रेणी के पदानुक्रम के हैं, तो आप बस उस आधार अपवाद प्रकार को पकड़ सकते हैं।

यह भी ध्यान दें कि आप अपवाद और अपवाद दोनों को एक ही ब्लॉक में नहीं पकड़ सकते हैं यदि ExceptionB विरासत में मिला है, या तो प्रत्यक्ष या अप्रत्यक्ष रूप से, अपवाद से। संकलक शिकायत करेगा:

Alternatives in a multi-catch statement cannot be related by subclassing
  Alternative ExceptionB is a subclass of alternative ExceptionA

81
टीटी - क्यों bitwise or( ए |) ऑपरेटर को फिर से परिभाषित करें ? अल्पविराम, या उस ऑपरेटर का उपयोग क्यों नहीं किया गया है जिसका अधिक समान अर्थ है, logical or( ||)?
आर्टऑफवर्फ

11
@ArtOfWarfare शायद उन्हें लगा कि जेनरिक के लिए कई सीमाओं के लिए पहले से ही सिंटैक्स के साथ आने के बाद अब यह कोई फर्क नहीं पड़ेगा ।
जिमीबी

12
XOR साइन (I) OR (()), A के समान नहीं है B का अर्थ A या B है लेकिन दोनों A नहीं || बी का अर्थ ए या बी या दोनों है, इसलिए अपवादों के लिए यह या तो अपवाद है या अपवाद बी लेकिन दोनों एक ही समय में नहीं। यही कारण है कि उन्होंने XOR का उपयोग OR के बजाय किया और आप देख सकते हैं कि जब अपवाद फेंकता है तो स्पष्ट रूप से यदि आप 2 अपवाद रखते हैं तो उनमें से एक उप का प्रकार है
user1512999

41
जावा में @ user1512999, बिटवाइज़ XOR ^ (कैरेट) और बिटवाइज़ या है | (पाइप) docs.oracle.com/javase/tutorial/java/nutsandbolts/op3.html
लुईस

6
यह उल्लेखनीय है कि मल्टी-कैच ब्लॉक में पकड़े गए अपवाद के प्रकार का मूल्यांकन सबसे व्युत्पन्न सामान्य माता
यान्प्स

104

जावा 7 से ठीक पहले नहीं, लेकिन, मैं कुछ इस तरह से करूंगा:

जावा 6 और उससे पहले

try {
  //.....
} catch (Exception exc) {
  if (exc instanceof IllegalArgumentException || exc instanceof SecurityException || 
     exc instanceof IllegalAccessException || exc instanceof NoSuchFieldException ) {

     someCode();

  } else if (exc instanceof RuntimeException) {
     throw (RuntimeException) exc;     

  } else {
    throw new RuntimeException(exc);
  }

}



जावा 7

try {
  //.....
} catch ( IllegalArgumentException | SecurityException |
         IllegalAccessException |NoSuchFieldException exc) {
  someCode();
}

11
ध्यान दें कि आपका जावा 6 उदाहरण यह बताने के लिए संकलक की क्षमता को तोड़ता है कि उसे कहां से फेंका जाएगा।
माइकलब्लू

2
@MichaelBlume सच है, जो [ऐसा] बुरा नहीं है। आप हमेशा मूल अपवाद प्राप्त कर सकते हैं exc.getCause()। एक साइड नोट के रूप में, रॉबर्ट सी। मार्टिन (दूसरों के बीच) अनियंत्रित अपवादों का उपयोग करने की सलाह देते हैं (कंपाइलर को इस बात का कोई पता नहीं है कि वहां से किस तरह का अपवाद फेंका जाएगा); अध्याय 7 का संदर्भ : उनकी पुस्तक क्लीन कोड पर त्रुटि को हैंडल करना ।
user454322

4
अपने जावा 6 उदाहरण में आपको एक नया अपवाद उदाहरण बनाने के बजाय मूल अपवाद को वापस नहीं लाना चाहिए, यानी के throw excबजाय throw new RuntimeException(exc)?
डेविड डेमार

5
यह पठनीयता के दृष्टिकोण से, बहुत बुरा अभ्यास है।
राजेश जे आडवाणी

3
Instanceof ऑपरेशन थोड़ा महंगा है, जितना संभव हो उतना बचने के लिए बेहतर है।
परमीश कोरकुट्टी

23

जावा 7 के भीतर आप कई कैच क्लॉस जैसे परिभाषित कर सकते हैं:

catch (IllegalArgumentException | SecurityException e)
{
    ...
}

16

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

try {
   ...
} catch (Exception e) {
   someCode();
}

एक अधिक सामान्य मामले में यदि रिपॉजिटरी एक्ससेप्शन बेस क्लास है और PathNotFoundException एक व्युत्पन्न क्लास है:

try {
   ...
} catch (RepositoryException re) {
   someCode();
} catch (Exception e) {
   someCode();
}

उपरोक्त कोड एक प्रकार के अपवाद से निपटने के लिए रिपोजिटरी अपवाद और PathNotFoundException को पकड़ लेगा और अन्य सभी अपवादों को एक साथ जोड़ दिया जाएगा। जावा 7 के बाद से, ऊपर @ OscarRyz के उत्तर के अनुसार:

try { 
  ...
} catch( IOException | SQLException ex ) { 
  ...
}

7
BTW कैच क्लॉज़ को क्रम में संभाला जाता है, इसलिए यदि आप एक चाइल्ड क्लास से पहले अभिभावक अपवाद वर्ग रखते हैं, तो इसे कभी भी नहीं बुलाया जाता है जैसे: {{}} पकड़ना (अपवाद ई) {someCode (); } catch (RepositoryException re) {// कभी नहीं पहुंचा}
माइकल शोप्सिन

4
वास्तव में ठीक है क्योंकि यह कभी नहीं पहुंच सकता है, इस तरह के कोड भी संकलन नहीं करता है।
पॉलीजेन लुब्रिकेंट्स

15

नहीं, एक प्रति ग्राहक।

जब तक आप सभी मामलों में एक जैसी कार्रवाई नहीं करेंगे, आप java.lang.Exception जैसे सुपरक्लास को पकड़ सकते हैं।

try {
    // some code
} catch(Exception e) { //All exceptions are caught here as all are inheriting java.lang.Exception
    e.printStackTrace();
}

लेकिन यह सबसे अच्छा अभ्यास नहीं हो सकता है। आपको केवल एक अपवाद को पकड़ना चाहिए जब आपके पास वास्तव में इसे संभालने की रणनीति हो - और लॉगिंग और रीथ्रोइंग "इसे संभालना" नहीं है। यदि आपके पास सुधारात्मक कार्रवाई नहीं है, तो इसे विधि हस्ताक्षर में जोड़ने के लिए बेहतर है और इसे किसी ऐसे व्यक्ति को सौंप दें जो स्थिति को संभाल सकता है।


20
क्या मैं आपको java.lang.Exception को पकड़ने वाले हिस्से के पुनर्निधारण के लिए याचिका दे सकता हूं? मुझे पता है कि यह एक उदाहरण है, लेकिन मुझे ऐसा लगता है कि कुछ लोग इस उत्तर को पढ़ सकते हैं और कह सकते हैं, "ओह, ठीक है, मैं अभी अपवाद को पकड़ लूंगा", जब कि शायद वे ऐसा नहीं करना चाहते (या करना चाहिए)।
रोब ह्रस्का

2
मैं इसके बारे में जानता था, लेकिन मैं ऐसा नहीं करना चाहता ... ओह, ठीक है, मुझे लगता है कि मैं 4 कैच के साथ फंस गया हूं, जावा के अगले संस्करण तक ...
फ्रैडी

@duffymo: लॉगिंग और रीथ्रोइंग में क्या गलत है? सिवाय इसके कि यह कोड को काटता है, इसे न पकड़ने के बराबर है, है न। सामान्य त्रुटि-हैंडलिंग रणनीति के दृष्टिकोण से देखा गया। क्या बुरा है और लॉगिंग नहीं है
फ्रैंक ओस्टरफेल्ड

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

क्या मैं अकेला हूँ जो यह पाता है कि मेरे लिए एक लॉग स्वतः उत्पन्न नहीं होता है? ऐसा लगता है कि हम सभी को एक ही बेवकूफ लॉगिंग संदेश को लिखना होगा जब भी कोड का कोई टुकड़ा अपवाद फेंक सकता है।
आर्टऑफवर्फ

10

जावा 6 (यानी, एंड्रॉइड) पर user454322 के उत्तर के लिए एक क्लीनर (लेकिन कम वर्बोज़, और शायद उतना पसंदीदा नहीं) का विकल्प सभी को पकड़ने Exceptionऔर फिर से फेंकने के लिए होगा RuntimeException। यह काम नहीं करेगा यदि आप अन्य प्रकार के अपवादों को पकड़ने की योजना बना रहे हैं, तो स्टैक को और बढ़ाएँ (जब तक कि आप उन्हें फिर से फेंक न दें), लेकिन प्रभावी रूप से सभी जाँच किए गए अपवादों को पकड़ लेंगे ।

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

try {
    // CODE THAT THROWS EXCEPTION
} catch (Exception e) {
    if (e instanceof RuntimeException) {
        // this exception was not expected, so re-throw it
        throw e;
    } else {
        // YOUR CODE FOR ALL CHECKED EXCEPTIONS
    } 
}

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


1
यह दृष्टिकोण कंपाइलर को यह निर्धारित करने से रोकता है कि "कैच ब्लॉक" उपलब्ध होगा या नहीं।
the_new_mr

3

पूर्व 7 में कैसे के बारे में:

  Boolean   caught = true;
  Exception e;
  try {
     ...
     caught = false;
  } catch (TransformerException te) {
     e = te;
  } catch (SocketException se) {
     e = se;
  } catch (IOException ie) {
     e = ie;
  }
  if (caught) {
     someCode(); // You can reference Exception e here.
  }

3
wuold एक अच्छा समाधान हो। caughtएक finallyब्लॉक में अंतिम नियंत्रण कैसे डालें ?
एंड्रिया_86

इसके लिए मूल प्रश्न से अधिक लाइनों की आवश्यकता होती है।
लिएंड्रो ग्लॉसमैन

1

हाँ। यहां पाइप (!) विभाजक का उपयोग करने का तरीका है,

try
{
    .......
}    
catch
{
    catch(IllegalArgumentException | SecurityException | IllegalAccessException | NoSuchFieldException e)
}

यह कोड शैली क्या है? एक कोशिश ब्लॉक में पकड़ ब्लॉक?
सैम

1

कोटलिन के लिए, यह अभी संभव नहीं है, लेकिन उन्होंने इसे जोड़ने पर विचार किया है: स्रोत
लेकिन अभी के लिए, बस एक छोटी सी चाल:

try {
    // code
} catch(ex:Exception) {
    when(ex) {
        is SomeException,
        is AnotherException -> {
            // handle
        }
        else -> throw ex
    }
}

0

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

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