2011-05-05 16 views
14

जावा में क्यों हम Exception पकड़ सकते हैं भले ही इसे फेंक दिया न जाए, लेकिन हम इसे "अनचेक" RuntimeException एस और उप-वर्गों को छोड़कर) को पकड़ नहीं सकते हैं। उदाहरण कोड:जावा पहुंच योग्य कैच ब्लॉक कंपाइलर त्रुटि

class Test { 
    public static void main(String[] args) { 
     try { 
      // do nothing 
     } catch (Exception e) { 
      // OK   
     } 

     try { 
      // do nothing 
     } catch (IOException e) { 
       // COMPILER ERROR: Unreachable catch block for IOException. 
       //This exception is never thrown from the try statement body 
     }  
    } 
} 

कोई विचार?

+1

इसका मतलब है कि पकड़ने के लिए कुछ भी नहीं है (कोई त्रुटि नहीं) मुझे समस्या नहीं दिखाई देती है – Neal

+3

आपको जावा भाषा विशिष्टता, या कम से कम एक अच्छा जावा ट्यूटोरियल पढ़ना चाहिए। –

उत्तर

25

RuntimeException कोड द्वारा फेंक दिया जा सकता है। दूसरे शब्दों में, संकलक आसानी से भविष्यवाणी नहीं कर सकता कि किस प्रकार का कोड इसे फेंक सकता है। को catch(Exception e) ब्लॉक द्वारा पकड़ा जा सकता है।

IOException, हालांकि, एक चेक अपवाद है - केवल विधि कॉल जिन्हें फेंकने के लिए घोषित किया जाता है, ऐसा कर सकता है। कंपाइलर (तर्कसंगत) विश्वास कर सकता है कि यह तब तक संभव नहीं हो सकता जब तक कि विधि कॉल नहीं किया जाता है जिसे इसे फेंकने के लिए घोषित किया जाता है।

जावा संकलक बस "बिल्कुल कोशिश ब्लॉक के भीतर कोई कोड नहीं है" स्थिति पर विचार नहीं करता है - यह हमेशा, सभी उचित परिदृश्यों में वहाँ के रूप में कोड होगा जो सकता है आप अनियंत्रित अपवाद को पकड़ने के लिए अनुमति देता है संभावित रूप से एक अनचेक अपवाद फेंक दें।

JLS की section 14.21 से

:

एक कैच ब्लॉक सी पहुंचा जा सकता है iff निम्न में से दोनों सही हैं:

  • कोशिश ब्लॉक में कुछ अभिव्यक्ति या फेंक बयान पहुंचा जा सकता है और फेंक कर सकते हैं एक अपवाद जिसका प्रकार कैच क्लॉज सी के पैरामीटर के लिए असाइन करने योग्य है। (एक अभिव्यक्ति को पहुंचने योग्य माना जाता है यदि इसमें शामिलतमतम कथन में पहुंच योग्य है।)
  • कोई कथन ब्लॉक ए नहीं है ch कि सी के पैरामीटर का प्रकार ए के पैरामीटर के प्रकार के उप-वर्ग के समान है।

यकीनन संकलक का एहसास होना चाहिए अपने पहले मामले में कोशिश ब्लॉक के भीतर कोई भाव देखते हैं कि ... ऐसा लगता है कि यह अभी भी एक नहीं पहुंचा जा सकता पकड़ खंड है की तरह मेरे लिए,।

संपादित करें: के रूप में टिप्पणी में बताया गया है, section 14.20 इस में शामिल हैं:

यह एक संकलन समय त्रुटि अगर एक catch खंड कैच अपवाद प्रकार जाँच E1 है, लेकिन कोई अपवाद प्रकार की जाँच की E2 वहां मौजूद इस तरह के जो निम्न पकड़ के सभी:

  • E2 <: E1
  • try ब्लॉक catch खंड के लिए इसी E2
  • फेंक कर सकते हैं तुरंत enclosing कोशिश बयान का कोई पूर्ववर्ती catch ब्लॉक E2 या E2 के महाप्रकार फैल जाती है।

जब तक ई 1 कक्षा अपवाद है।

तो ऐसा लगता है कि यह है कि क्या आप वास्तव में रहे की बेईमानी से चल रहा है, लेकिन कल्पना के रूप में स्पष्ट रूप में यह 14.21 में पहुंच योग्य नहीं पकड़ ब्लॉक के मामले में हो सकता है नहीं है।

+0

मुझे लगता है कि समाधान [§ 14.20] (http://java.sun.com/docs/books/jls/third_edition/html/statements में है।एचटीएमएल # 79311), जो स्पष्ट रूप से कहता है कि "अपवाद" से "अपवाद" का पता लगाना चाहिए: "[...] जब तक *' E1' * वर्ग 'अपवाद' वर्ग नहीं है। –

+0

@ जोचिम: ठीक है। जवाब में जोड़ देंगे। –

0

बस जावा मानता है कि कोई भी कोड लाइन एक सामान्य Exception या Throwable यानी फेंक सकती है। OutOfMemoryException जो Error है बल्कि Exception है। एनपीई के लिए भी लागू होता है।

IOException एक विशिष्ट अपवाद है जिसे केवल प्रबंधित कोड द्वारा फेंक दिया जा सकता है, इसलिए यदि आपके पास आपके कंपाइलर में आई/ओ कॉल नहीं है तो इसे पकड़ने का कोई मौका नहीं है।

सी # दुनिया की तुलना करने के लिए, सी # ऐसे कोड में संकलित किया जाएगा लेकिन एक वैचारिक गलती होगी क्योंकि यदि आप कुछ भी नहीं करते हैं तो आप पकड़ ब्लॉक तक नहीं पहुंचते हैं। ReSharper जैसे टूल आपको इसके बारे में चेतावनी दे सकते हैं।

+6

अंतर यह है कि 'IOException' (और इसके सभी उप-प्रकार) ** ** अपवाद ** अपवाद हैं, इसलिए कंपाइलर ** बिल्कुल ** कह सकता है कि कौन से कथन * उन्हें फेंक सकते हैं। 'अपवाद' में 'रनटाइम अपवाद' शामिल है और इसलिए * किसी भी कथन में * हो सकता है (क्योंकि उन्हें अनचेक किया गया है और घोषित नहीं किया जाना चाहिए)। –

2

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

3

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

1

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

5

आईओ अपवाद केवल तभी पकड़े जा सकते हैं जब संकलक भविष्यवाणी करता है कि IOException को फेंकने वाले कोड में कुछ ऐसा हो सकता है। तो आपको एक चेतावनी मिल रही है कि आईओ अपवाद को कभी भी कथन कथन निकाय से नहीं फेंक दिया जाता है (क्योंकि कोशिश के शरीर में कुछ भी नहीं है)।

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