कोशिश / पकड़ बनाम फेंकता अपवाद


117

क्या ये कोड स्टेटमेंट समकक्ष हैं? क्या उनके बीच कोई अंतर है?

private void calculateArea() throws Exception {
    ....do something
}

private void calculateArea() {
    try {
        ....do something
    } catch (Exception e) {
        showException(e);
    }
}

3
वास्तव में एक उत्तर नहीं है, लेकिन आप नेड बैचेलेडर के लेख एक्सेप्शन इन रेनफॉरेस्ट में दिलचस्पी ले सकते हैं , जो सामान्य मामलों को समझाने में मदद करता है जहां एक शैली या दूसरे को पसंद किया जाना है।
डैनियल प्रीडन जू

1
बजाय पकड़ में "showException (e)" होने के बजाय, क्या आप पूछ रहे थे कि क्या आपके पास पकड़ में "throws e" था (या कोशिश / कैच बिल्कुल नहीं)?
मैकगिवर

जवाबों:


146

हां, एक बड़ा अंतर है - बाद वाला अपवाद निगलता है (इसे दिखा रहा है, संयुक्त रूप से), जबकि पहले वाला इसे प्रचारित करेगा। (मैं मान रहा हूँ कि showExceptionइसे पुनर्विचार नहीं करता है।)

इसलिए यदि आप पहली विधि कहते हैं और "कुछ करते हैं" विफल रहता है, तो कॉलर को अपवाद को संभालना होगा। यदि आप दूसरी विधि कहते हैं और "कुछ करते हैं" विफल रहता है, तो फोन करने वाले को एक अपवाद दिखाई नहीं देगा ... जो आम तौर पर एक बुरी बात है, जब तक showExceptionकि वास्तव में अपवाद को संभाला नहीं है, जो कुछ भी गलत था, और आम तौर पर सुनिश्चित किया गया है कि calculateAreaअपने उद्देश्य हासिल की है।

आप यह बताने में सक्षम होंगे, क्योंकि आप पहली विधि को या तोException खुद को पकड़ने या घोषित करने के बिना नहीं कह सकते हैं कि आपकी विधि इसे भी फेंक सकती है।


12
जब आप उल्लेख करते हैं कि "जब तक कि यह वास्तव में अपवाद को नियंत्रित नहीं करता है", यह एक महान बिंदु है। मुझे लगा कि मैं "अपवाद" को पकड़ने के लिए खुद को शायद ही कभी वास्तविक अपवाद के बुद्धिमान "हैंडलिंग" की ओर ले जाऊंगा, यही कारण है कि लोग आपको सबसे विशिष्ट अपवाद को पकड़ने की सलाह देते हैं।
बिल के

17
+1। क्योंकि जॉन स्कीट को अधिक प्रतिष्ठा की आवश्यकता है। ओह, और जवाब भी अच्छा था।
जोनाथन स्पिलर

20

पहले एक throws Exception, तो फोन करने वाले को संभालने की जरूरत है Exception। दूसरा व्यक्ति Exceptionआंतरिक रूप से पकड़ता है और संभालता है , इसलिए कॉल करने वाले को किसी भी अपवाद से निपटने की आवश्यकता नहीं है।


तो संक्षेप में, मुझे हमेशा दूसरे का उपयोग करना चाहिए। क्या मैं सही हू? पहला एक वास्तव में एक विधि है जिसका उपयोग कार्यक्रम के विभिन्न बिंदुओं में किया जाता है। इसीलिए मैंने आगे के उपयोग के निर्देशों को एक साथ करने का फैसला किया, लेकिन ऐसा किया कि मुझे अब एहसास हुआ कि T एक बड़ी गलती कर रहा था ..
carlos

9
नहीं, दोनों पैटर्न की जरूरत है। यदि आपकी विधि अपवाद को संभाल सकती है, तो दूसरे पैटर्न का उपयोग करें, यदि नहीं, तो कॉल करने वाले को पहले एक का उपयोग करें।
एंड्रियास डॉक

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

16

हाँ। जो संस्करण घोषित करता है throws Exceptionउसे अपवाद को संभालने के लिए कॉलिंग कोड की आवश्यकता होगी, जबकि संस्करण जो स्पष्ट रूप से संभालता है वह नहीं होगा।

अर्थात्, बस:

performCalculation();

बनाम फोन करने वाले के अपवाद को संभालने का बोझ बढ़ रहा है:

try {
    performCalculation();
catch (Exception e) {
    // handle exception
}

6

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

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


3

एक विशेष परिदृश्य है जहाँ हम थ्रो का उपयोग नहीं कर सकते हैं, हमें ट्राइ-कैच का उपयोग करना है। एक नियम है "एक ओवरराइड विधि अपने मूल वर्ग को फेंकने के अलावा कोई अतिरिक्त अपवाद नहीं फेंक सकती है"। यदि कोई अतिरिक्त अपवाद है जिसे ट्राइ-कैच का उपयोग करके नियंत्रित किया जाना चाहिए। इस कोड स्निपेट पर विचार करें। एक साधारण आधार वर्ग है

package trycatchvsthrows;

public class Base {
    public void show()
    {
        System.out.println("hello from base");
    }
}

और यह व्युत्पन्न वर्ग है:

package trycatchvsthrows;

public class Derived extends Base {

    @Override
    public void show()   {
        // TODO Auto-generated method stub
        super.show();

        Thread thread= new Thread();
        thread.start();
        try {
            thread.sleep(100);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        // thread.sleep(10);
        // here we can not use public void show() throws InterruptedException 
        // not allowed
    }
}

जब हमें थ्रेड को कॉल करना होता है। सो () हम ट्राइ-कैच का उपयोग करने के लिए मजबूर होते हैं, यहाँ हम उपयोग नहीं कर सकते हैं:

 public void show() throws InterruptedException

क्योंकि ओवरराइड विधि अतिरिक्त अपवादों को नहीं फेंक सकती है।


मेरा मानना ​​है कि हर कोई इस चेतावनी के बारे में नहीं जानता है। खैर इशारा किया।
ivanleoncz

1

मुझे लगता है कि "समान" द्वारा आप व्यवहार की बात कर रहे हैं।

किसी फ़ंक्शन का व्यवहार निम्न द्वारा निर्धारित किया जा सकता है:

1) लौटाया गया मान

2) अपवाद छोड़ दें

3) साइड इफेक्ट्स (यानी ढेर में परिवर्तन, फ़ाइल सिस्टम आदि)

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

हालांकि, यदि आप गारंटी देते हैं कि "कुछ करें" कभी अपवाद नहीं फेंकता है, तो व्यवहार समान होगा (हालांकि कंपाइलर को अपवाद को संभालने के लिए कॉलर की आवश्यकता होगी, पहले संस्करण में)

--edit--

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


1

यदि आप एक अपवाद फेंक देते हैं, तो बाल विधि (जो इसे ओवरराइड करती है) को अपवाद को संभालना चाहिए

उदाहरण:

class A{
public void myMethod() throws Exception{
 //do something
}
}

A a=new A();
try{
a.myMethod();
}catch Exception(e){
//handle the exception
}

0

कई बार आप चाहते हैं कि कॉलर अपवाद को संभालें। मान लें कि आपके पास कॉलर कॉल एक ऐसी विधि है, जो किसी अन्य विधि को कॉल करती है, जो किसी अन्य विधि को कॉल करती है, इसके बजाय प्रत्येक विधि अपवाद को संभालती है, तो आप बस कॉलर पर इसे संभाल सकते हैं। जब तक, आप उस विधि के विफल होने पर किसी एक विधि में कुछ करना चाहते हैं।


0

इस विधि के कॉलर को या तो इस अपवाद को पकड़ने की आवश्यकता होगी या इसे विधि हस्ताक्षर में पुनः घोषित करने की घोषणा करनी होगी।

private void calculateArea() throws Exception {
    // Do something
}

नीचे दिए गए ट्राइ-कैच ब्लॉक उदाहरण में। इस विधि के कॉलर को अपवाद को संभालने के लिए चिंता करने की ज़रूरत नहीं है क्योंकि यह पहले से ही ध्यान रखा गया है।

private void calculateArea() {
    try {
        // Do something

    } catch (Exception e) {
        showException(e);
    }
}

0
private void calculateArea() throws Exception {
    ....do something
}

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

जबकि दूसरे मामले में:

private void calculateArea() {
    try {
        ....do something
    } catch (Exception e) {
        showException(e);
    }
}

यहां अपवाद को कैली द्वारा नियंत्रित किया गया है, इसलिए कार्यक्रम की असामान्य समाप्ति का कोई मौका नहीं है।

पकड़ने की कोशिश अनुशंसित दृष्टिकोण है।

IMO,

  • कंपाइलर को समझाने के लिए चेक किए गए अपवादों के साथ ज्यादातर थ्रो कीवर्ड का उपयोग किया जाता है, लेकिन यह प्रोग्राम की सामान्य समाप्ति की गारंटी नहीं देता है।

  • थ्रो कीवर्ड
    कॉल करने वाले (JVM या किसी अन्य विधि) को अपवाद हैंडलिंग की जिम्मेदारी सौंपता है।

  • फेंके गए कीवर्ड की जाँच अपवादों के लिए आवश्यक है, अनियंत्रित अपवादों के लिए थ्रो कीवर्ड का कोई उपयोग नहीं है।

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