2010-04-12 19 views
19

क्या आप सहमत हैं कि जावा क्लास java.io.IOException के डिजाइनरों को इसे java.lang.Exception से प्राप्त किए गए चेक अपवाद के बजाय java.lang.RuntimeException से निकाला गया एक अनचेक रन-टाइम अपवाद होना चाहिए था?जावा में कक्षा IOException एक अनचेक RuntimeException होना चाहिए?

मुझे लगता है कि कक्षा IOException एक अनचेक अपवाद होना चाहिए क्योंकि फ़ाइल सिस्टम त्रुटियों जैसी समस्याओं को हल करने के लिए कोई एप्लिकेशन ऐसा नहीं कर सकता है। हालांकि, When You Can't Throw An Exception में, Elliotte Rusty Harold दावा है कि सबसे आई/ओ त्रुटियों क्षणिक होते हैं और इसलिए आप एक आई/ओ आपरेशन कई बार देने से पहले पुन: प्रयास कर सकते हैं:

उदाहरण के लिए, एक IOComparator एक मैं नहीं ले सकता है/O त्रुटि लेटी, लेकिन - क्योंकि कई मैं/हे समस्याओं क्षणिक होते हैं - आप कुछ समय, के रूप में लिस्टिंग 7 में दिखाया गया है पुन: प्रयास कर सकते हैं:

यह आम तौर पर मामला है? क्या जावा एप्लिकेशन सही I/O त्रुटियों को ठीक कर सकता है या सिस्टम को पुनर्प्राप्त करने का इंतजार कर सकता है? यदि ऐसा है, तो IOException की जांच के लिए उचित है, लेकिन यदि यह मामला नहीं है, तो IOException अनचेक किया जाना चाहिए ताकि व्यावसायिक तर्क इस अपवाद के एक अलग सिस्टम त्रुटि हैंडलर को संभालने का प्रतिनिधि हो सके।

+12

कई लोगों को लगता है कि हर अपवाद अनियंत्रित किया जाना चाहिए था ... – leonbloy

+4

बहुत से लोग जो अपवादों पर विचार करने की जरूरत है वे जानना चाहते हैं कि हो सकता है। –

+3

@ Thorbjørn: मुझे संदेह है कि यह एक संयोग है कि किसी भी अन्य भाषा ने chekced अपवाद मॉडल की प्रतिलिपि बनाई है। यह एक दिलचस्प प्रयोग था, सिद्धांत में अच्छा लगता है, लेकिन अभ्यास में अच्छा से कहीं अधिक नुकसान करता है। –

उत्तर

16

मैं पूरी तरह से असहमत हूं। मेरे लिए मॉडल सही है। एक RuntimeException एक ऐसा है जो प्रोग्रामिंग के तर्क (जैसे ArrayIndexOutOfBounds, NullPointer, या IllegalArgument) में किसी गंभीर त्रुटि को इंगित करता है या कुछ ऐसा जो रनटाइम अन्यथा निर्धारित होता है वास्तव में नहीं होना चाहिए (जैसे सुरक्षा अपवाद)।

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

मुझे लगता है कि वहाँ कई स्थितियों जिसमें एक IOException या तो वसूली योग्य है, या कम से कम प्रोग्रामर ताकि अगर यह प्रणाली वसूली योग्य नहीं है और अधिक "धीरे" दुर्घटना करने में सक्षम हो सकता है की क्षमता का स्पष्ट रूप से पता होना चाहिए ।

अब तक आपके विचार के बारे में सोचा कि सिस्टम ठीक नहीं हो सकता है, वहां हमेशा चेक अपवाद के साथ विकल्प होते हैं। मुझे लगता है कि यह एक जाँच अपवाद छोड़ने के लिए चालाक है

public void doit() throws IOException { 
    try{ 
    }catch(IOException e){ 
    // try to recover 
    ... 

    // can't recover 
    throw e; 
    } 
} 

public void doit() { 
    try{ 
    }catch(IOException e){ 
    // try to recover 
    ... 

    // can't recover 
    throw new RuntimeException(e); 
    } 
} 



public void doit() { 
    try{ 
    }catch(IOException e){ 
    // try to recover 
    ... 

    // OH NO!!!! 
    System.exit(Constant.UNRECOVERABLE_IO_ERROR); 
    } 
} 
+6

http://www.oracle.com/technology/pub/articles/dev2arch/2006/11/effective-exceptions.html में, बैरी रुज़ेक इस बात से असहमत हैं: "एक आई/ओ विफलता एक गंभीर लेकिन अत्यंत दुर्लभ घटना है। शीर्ष पर उसमें, आमतौर पर आपके कोड को एक से पुनर्प्राप्त करने के लिए कुछ भी नहीं किया जा सकता है। " रुज़ेक के अनुसार, कई जावा पुस्तकालय इस अपवाद को फेंक देते हैं, जो बताता है कि वे 'IOException' से पुनर्प्राप्त करने के लिए आपके पहले दृष्टिकोण का पालन करते हैं। हालांकि, अगर कुछ विधि 'IOException' से पुनर्प्राप्त करने में विफल होती है, तो यह अधिक संभावना है कि क्लाइंट वैसे भी ठीक हो सकता है, तो इसे अधिक फेंकने का क्या मतलब है? –

+5

मैं "बेहद दुर्लभ" घटनाओं से असहमत हूं। नेटवर्क सॉकेट पर विचार करें। क्लाइंट सॉकेट डिस्कनेक्ट होने के लिए यह पूरी तरह से उचित है और यदि आप डेटा लिखने या पढ़ने की कोशिश कर रहे हैं तो यह IOException का कारण बन जाएगा। वसूली के लिए मुझे लगता है कि आपको "वसूली" की अपनी परिभाषा के बारे में सावधान रहना होगा। सॉकेट उदाहरण में आप क्लाइंट कनेक्शन खो सकते हैं, लेकिन रिकवरी एक ऐसी प्रक्रिया हो सकती है जैसे संसाधनों को मुक्त करना जो कटे हुए कनेक्शन द्वारा उपयोग किए जाते थे। इसी प्रकार पुनर्स्थापना के लिए आप उत्प्रेरक के करीब की घटना को लॉग करना चाहते हैं, लेकिन इससे निपटने के लिए स्टैक को ऊपर उठाने की अनुमति दें। –

+0

तो वसूली विफल होने के बाद आप किस मामले में 'रनटाइम अपवाद' को फिर से फेंकने की सलाह देंगे? क्या यह अनचाहे 'IOException' से थोड़ा अलग नहीं है (और उतना ही बुरा है)? –

2

नहीं क्योंकि आप कुछ IOExceptions से पुनर्प्राप्त कर सकते हैं। सबसे उल्लेखनीय वाले निम्न स्तर अनुक्रमित पढ़ते हैं और लिखते हैं। यदि यह विफल रहता है, तो कभी-कभी आप बिना नुकसान के पुनः प्रयास कर सकते हैं।

5

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

+1

मैं भाषा डिजाइन में ** बग ** के रूप में चेक अपवादों का सम्मान करता हूं। आप इसे स्वयं कहते हैं: IOExcpetion संदेश उपयोगकर्ता को जानकारीपूर्ण हो सकता है - लेकिन निम्न स्तर की आईओ विधि के लिए क्या अच्छा है कि यूआई के साथ कोई व्यवसाय नहीं है और फिर भी इसके साथ अपवाद को पकड़ने या उसके हस्ताक्षर को प्रदूषित करने के लिए मजबूर किया गया है? –

+0

माइकल, क्या आपका मतलब है कि निम्न-स्तरीय I/O विधि अपवाद को पकड़ने और उसके हस्ताक्षर, या यूआई स्तर कोड को प्रदूषित करने के लिए मजबूर है? –

+2

@ माइकल: आईएमओ हस्ताक्षर बिल्कुल प्रदूषित नहीं है। जैसे ही आप लौटाए गए मान प्रकार को निर्दिष्ट करते हैं, आपको कार्रवाई के अन्य प्रकार के वैध परिणामों को भी निर्दिष्ट करना चाहिए। इसमें व्यावहारिक और घोषणात्मक महत्व दोनों हैं। –

3

शायद आईओ अपवादों का विशाल बहुमत पुनर्प्राप्त करने योग्य है - अनुमति त्रुटियों, ड्राइव पर स्थान की कमी, कनेक्शन बंद, इत्यादि।मेरा मानना ​​है कि अनचेक अपवादों का उपयोग इस तरह के परिस्थितियों से ठीक होने का कोई उचित तरीका नहीं है।

1

एक अच्छी तरह से डिज़ाइन किए गए अपवाद ढांचे में, कुछ हद तक "अपेक्षित" और जो नहीं हैं अपवादों के बीच एक भेद किया जाना चाहिए। जावा इसके लिए अनचेक अपवादों के विरुद्ध चेक-इन का उपयोग करने का प्रयास करता है। उस मानक से, IOException एक अपवाद अपवाद होना चाहिए।

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

try 
{ 
    methodThatsDeclaredAsThrowingFooExceptionButWont() 
} 
catch FooException Ex 
{ 
    // Never going to happen 
} 

स्पष्ट धारणा वहाँ catch करने के लिए कोई कारण नहीं है के बाद से विधि FooException और एकमात्र कारण catch वहाँ संकलक खुश करने के लिए है, फेंक नहीं होगा कि है कुछ भी। कपटी, क्योंकि अगर FooException फेंक दिया जाता है, किसी भी कारण से, यह ज्ञात नहीं होगा।

एक वैकल्पिक एक तरीका है जिसके methodThatsDeclaredAsThrowingFooExceptionButWont throws FooException या throws Exception के रूप में घोषित करने के लिए कॉल के लिए है, लेकिन है कि या तो वास्तव में उचित नहीं है। यदि FooException फेंकने की कोई विधि नहीं है, तो सिस्टम स्थिति FooException फेंकने पर अपेक्षा की जा सकती है।

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

उचित उपाय IOException के लिए एक अनचेक अपवाद होने के लिए नहीं होगा, बल्कि इसके बजाय एक घोषणात्मक माध्यम होने के लिए कौन सा कोड इंगित कर सकता है कि एक या अधिक प्रकार के चेक अपवादों को किसी निश्चित से बाहर निकलने की अनुमति नहीं दी जानी चाहिए इस प्रकार बुलाए गए तरीकों से ब्लॉक करें, लेकिन इसके बजाय किसी अन्य अपवाद प्रकार (जैसे रनटाइम अपवाद) में लपेटा जाना चाहिए।

9

मैं जानता हूँ कि यह 4 साल कर दिया गया है के बाद से इस प्रश्न पूछा गया था, लेकिन एक UncheckedIOException जावा में जोड़ा गया था 8.

+3

जावा 8 एपीआई डिजाइनरों ने मेरा प्रश्न पढ़ना होगा! अंत में, मुझे स्वयं को 'अनचेकियोएक्सप्शन' का आविष्कार करना चाहिए और एपीआई को कॉपीराइट करना चाहिए ताकि ओरेकल को मुझे लाइसेंस शुल्क का भुगतान करना पड़े। :) –

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