2011-06-15 21 views
5

Let कहते हैं कि मैं इस इंटरफेस एक कि कई विक्रेताओं द्वारा कार्यान्वित किया जाता है है:जावा: एक इंटरफ़ेस विधि घोषित करने का उचित तरीका क्या है जो अपवाद फेंक सकता है?

interface A 
{ 
    void x(); 
    void y(); 
} 

हालांकि, मैं विक्रेताओं कुछ संकेत देने के लिए अपवाद फेंक करने में सक्षम में नाकाम रही है होना चाहता हूँ और संभावित विधि एक RuntimeException फेंक सकता है। प्रत्येक मामले में, इन विधियों को कॉल करने वाले कोड को विफलता को संभालना चाहिए और जारी रखना चाहिए। सिर्फ इसलिए कि 1 विक्रेता एनपीई फेंकता है, मैं नहीं चाहता कि सिस्टम क्रैश हो जाए। (या वास्तव में लाइन के रखरखाव के नीचे) व्यक्ति विधि बुला के लिए इसे छोड़ने के बजाय, मुझे यकीन है कि प्रत्येक कॉल के रूप में प्रत्येक विधि की घोषणा के द्वारा सभी अपवादों को पकड़ेगा बनाने के लिए करना चाहते हैं:

void x() throws Exception; 

लेकिन आम तौर पर खराब है अभ्यास (पीएमडी इसे पसंद नहीं करता है और आम तौर पर मैं ठोस तरीकों के लिए नियम से सहमत हूं) तो मुझे आश्चर्य है कि यह नियम के लिए अपवाद है या क्या कोई बेहतर तरीका है?

मुझे स्पष्ट होने दें, मैं ऐसे समाधान की तलाश में हूं जहां इंटरफ़ेस के कॉलर को सभी अपवादों को संभालने के लिए मजबूर किया गया है (RuntimeException एस सहित)।

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

+0

यह प्रश्न इंटरफेस के लिए विशिष्ट नहीं है, है ना? मेरा मतलब है, वही मुद्दे अमूर्त तरीकों और यहां तक ​​कि विधि कार्यान्वयन पर भी लागू होते हैं जो हो सकता है (या यहां तक ​​कि होने की उम्मीद भी हो सकती है)। –

+0

यदि यह विधि 'कुछ' कर रही है तो यह इतना व्यापक है कि यह संभवतः कोई अपवाद फेंक सकता है? – blank

+0

अपवादों के सेट को बाधित करना मुश्किल होगा, इसलिए हां। –

उत्तर

7

अपनी खुद की अपवाद कक्षा यानी बनाएँ। MySeviceException और इसे इंटरफ़ेस से फेंक दें। यहां विचार सार्थक अपवादों को फेंकना है इसलिए कई कस्टम अपवाद वर्गों को बनाने से डरो मत, अगर यह आपके उद्देश्यों के लिए अधिक पठनीयता और रखरखाव प्रदान करता है। आप डाउनस्ट्रीम में विक्रेता विस्तृत अपवादों को पकड़ सकते हैं और उन्हें अपने कस्टम अपवाद के रूप में लपेट सकते हैं ताकि अपस्ट्रीम प्रवाह को विक्रेता विशिष्ट अपवादों से निपटने की आवश्यकता न हो।

class MySeviceException extends Exception{ 
    public MySeviceException() {} 
    public MySeviceException(String msg) { super(msg); } 
    public MySeviceException(Throwable cause) { super(cause); } 
    public MySeviceException(String msg, Throwable cause) { super(msg, cause); } 
} 

interface A 
{ 
    void x() throws MySeviceExceptionException; 
    void y() throws MySeviceExceptionException; 
} 

एक सामान्य नियम के Errors पकड़ने कभी नहीं के रूप में, हमेशा Exceptions को पकड़ने और इसके साथ सौदा!

+0

मुझे यह विचार पसंद है लेकिन यह कॉलर्स को रनटाइम अपवादों की जांच करने के लिए मजबूर नहीं करता है। शायद मुझे बस दोनों को फेंकने की घोषणा करनी होगी। –

+3

@ डेव एच - आप रनटाइर्स को रनटाइम अपवादों की जांच करने के लिए बल नहीं दे सकते (और कोशिश नहीं कर सकते), यह एक अनचेक अपवाद की प्रकृति है। – Robin

2

विक्रेताओं निश्चित रूप से, क्योंकि वे अनियंत्रित हो, उनके दिल की सामग्री के लिए RuntimeException फेंक कर सकते हैं। इसका मतलब है कि आपको इंटरफ़ेस में throws खंड जोड़ने की आवश्यकता नहीं है।

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

आपको लगता है कि java.lang.Exception फैली एक कस्टम अपवाद बना सकते हैं; यह एक चेक अपवाद है। आपको इसे फेंकने वाले खंड में जोड़ना होगा; संकलक उन तरीकों के चारों ओर एक कोशिश/पकड़ लागू करेगा; आपके ग्राहकों को समस्या को संभालना होगा।

+0

मैं जावाडॉक्स पर भरोसा करने के बजाय कुछ और कंपाइलर लागू करने योग्य खोज रहा हूं। –

+0

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

+0

इसके अलावा आप सभी सेवा कॉल को {} पकड़ (अपवाद ई) – nsfyn55

1

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

कुछ कोड है कि अपने इंटरफेस को लागू करता है में गलत हो जाता है, कि लागू करने वर्ग के प्रोग्रामर की चिंता होनी चाहिए।

+0

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

1

कस्टम अपवाद प्रकार के साथ भी फेंकता खंड बनाना, वास्तव में यहां कोई जवाब नहीं है। आप हमेशा एनपीई जैसी चीजें रखने जा रहे हैं। भले ही आप विक्रेताओं को निर्दिष्ट करते हैं कि सभी अपवादों को आपके कस्टम अपवाद प्रकार में लपेटा जाना चाहिए, ऐसे मामले होने जा रहे हैं जहां कोई गलती करता है और एनपीई हो जाता है। अगर यह गलतियों के लिए नहीं था तो आपके पास एनपीई नहीं होगा।

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

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

+0

मैंने मूल प्रश्न संपादित किया है। मैं ओएसजीआई का उपयोग कर रहा हूं इसलिए एप्लिकेशन वास्तव में बाहर नहीं निकलता है, यह अधिक है कि मौजूदा ऑपरेशन 1 खराब सेब के कारण बाधित है। –

1

मैं पीएमडी से सहमत हूं - यह घोषणा करते हुए कि आप जेनेरिक Exception एस बदसूरत हैं। मुझे लगता है कि यह

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

जावा के हाल के संस्करण आपको श्रृंखला अपवादों की अनुमति देते हैं। उदाहरण के लिए, यदि आप प्राप्त NullPointerException ex जबकि एक बाहरी पुस्तकालय के साथ एक File f पार्स करने, आप इसे पकड़ने और के रूप में, कहते हैं यह rethrow चाहेगा एक, एक new FileParsingException("error parsing " + f + ": " + ex.getMessage(), ex);

+0

क्षमा करें, लेकिन यह भयानक है, आप अपवादों की मात्रा बढ़ाते हैं और आखिरकार कस्टम अपवाद आपको वास्तव में गलत होने के बारे में कुछ भी नहीं बताता है, इसलिए आपको आंतरिक अपवादों और सामग्री को फेंकने के दौरान वास्तविक कारण खोजने के लिए पुरातत्व खोदना होगा, अपवाद तुरंत आपको बताएगा कि क्या है गलत हो गया ... – Enerccio

+0

मैं दृढ़ता से असहमत हूं। लपेटने के अपवाद * इस मामले को संभालने का अनुशंसित तरीका है (जैसा कि स्वीकृत उत्तर द्वारा वकालत की गई है, जो बेहतर लिखा गया है लेकिन अन्यथा इस उत्तर के समान ही है); क्योंकि रैपिंग अन्यथा अनुपलब्ध संदर्भ जोड़ता है। इस उत्तर के उदाहरण में, एक अनचाहे एनपीई आपको एक विकृत फ़ाइल का निदान करने में कैसे मदद करेगा जो पार्सर को तोड़ देता है? – tucuxi

1

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

देखें सूर्य/ओरेकल की अपवाद

http://download.oracle.com/javase/tutorial/essential/exceptions/runtime.html

के बारे में ट्यूटोरियल काफी अटक फेंक अपवाद सवाल का जवाब करने के लिए, जब तक आप जानते हैं कि वास्तव में क्या अपवाद व्युत्पन्न आप फेंकने किए जाने की उम्मीद कर सकते हैं, तो आप कर रहे हैं, हालांकि मैं जेनेरिक अपवाद वर्ग को फेंकने की उपयोगिता के रूप में प्रमुख संदेह हैं, जब तक कि आप केवल स्टैक ट्रेस को लॉग आउट करने की परवाह नहीं करते हैं और ऐसा आप जानते हैं कि यह हुआ? यदि आप बिना किसी अपवाद के जानने के अपवाद को मजबूती से संभालने की कोशिश कर रहे हैं, तो संभवतः आप इसे ठीक से या यहां तक ​​कि पर्याप्त रूप से संभालने में बहुत सफल नहीं होंगे।

+0

यह सुनिश्चित करने के बारे में अधिक है कि विक्रेता बंडल सिस्टम को चलने से नहीं रोकता है। यह एक प्लग-इन फ्रेमवर्क है जहां कई विक्रेताओं से प्लग-इन वांछित के रूप में जोड़ा जा सकता है। –

1

आप अपने इंटरफ़ेस को एक सारणी कक्षा में कार्यान्वित कर सकते हैं जो कस्टम अपवाद के साथ RuntimeExceptions को पकड़ने और लपेटने के लिए टेम्पलेट विधि पैटर्न का उपयोग करता है। हालांकि, यह लागू करने का कोई तरीका नहीं है कि विक्रेता अमूर्त वर्ग (दस्तावेज़ीकरण के अलावा) का उपयोग करें।

class MySeviceException extends Exception{ 
    public MySeviceException() {} 
    public MySeviceException(String msg) { super(msg); } 
    public MySeviceException(Throwable cause) { super(cause); } 
    public MySeviceException(String msg, Throwable cause) { super(msg, cause); } 
} 

interface A 
{ 
    void x() throws MySeviceExceptionException; 
    void y() throws MySeviceExceptionException; 
} 

class ABase implements A 
{ 
    public final void x() throws MySeviceExceptionException { 
     try { 
      doX(); 
     } catch(RuntimeException ex) { 
      throw new MySeviceExceptionException(ex); 
     } 
    } 
    public final void y() throws MySeviceExceptionException { 
     try { 
      doY(); 
     } catch(RuntimeException ex) { 
      throw new MySeviceExceptionException(ex); 
     } 
    } 

    public abstract void doX() throws MySeviceExceptionException; 
    public abstract void doY() throws MySeviceExceptionException; 
} 
संबंधित मुद्दे

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