नमस्ते! मुझे इसका जिक्र करने से नफरत है, लेकिन प्रोग्रामर के काम का एक बड़ा हिस्सा त्रुटियों से निपट रहा है। बहुधा, उसका अपना। यह पता चला है कि ऐसे लोग नहीं हैं जो गलतियाँ नहीं करते हैं। और ऐसा कोई कार्यक्रम भी नहीं है। बेशक, किसी त्रुटि से निपटने के दौरान, मुख्य बात यह है कि इसके कारण को समझना है. और बहुत सी चीजें प्रोग्राम में बग पैदा कर सकती हैं। किसी बिंदु पर, जावा के रचनाकारों ने खुद से पूछा कि सबसे संभावित प्रोग्रामिंग त्रुटियों के साथ क्या किया जाना चाहिए? पूरी तरह से उनसे बचना यथार्थवादी नहीं है, प्रोग्रामर ऐसी चीजें लिखने में सक्षम हैं जिनकी आप कल्पना भी नहीं कर सकते। :) इसलिए, हमें भाषा को त्रुटियों के साथ काम करने के लिए एक तंत्र देने की आवश्यकता है। दूसरे शब्दों में, यदि आपके प्रोग्राम में कोई त्रुटि है, तो आगे क्या करना है इसके लिए आपको किसी प्रकार की स्क्रिप्ट की आवश्यकता होगी। त्रुटि होने पर प्रोग्राम को वास्तव में क्या करना चाहिए? आज हम इस तंत्र से परिचित होंगे। इसे " जावा में अपवाद " कहा जाता है।
अपवाद क्या है?
एक अपवाद एक असाधारण, अनियोजित स्थिति है जो तब होती है जब कोई प्रोग्राम चल रहा होता है। कई अपवाद हैं। उदाहरण के लिए, आपने कोड लिखा है जो फ़ाइल से पाठ पढ़ता है और पहली पंक्ति प्रदर्शित करता है।
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader reader = new BufferedReader(new FileReader("C:\\Users\\Username\\Desktop\\test.txt"));
String firstString = reader.readLine();
System.out.println(firstString);
}
}
लेकिन क्या होगा अगर ऐसी कोई फाइल नहीं है! कार्यक्रम एक अपवाद उत्पन्न करेगा: FileNotFoundException
. आउटपुट: थ्रेड में अपवाद "मुख्य" java.io.FileNotFoundException: C:\Users\Username\Desktop\test.txt (सिस्टम निर्दिष्ट पथ नहीं ढूंढ सकता) जावा में, प्रत्येक अपवाद को एक अलग वर्ग द्वारा दर्शाया गया है। ये सभी अपवाद वर्ग एक सामान्य "पूर्वज" - Throwable
मूल वर्ग से प्राप्त होते हैं। एक अपवाद वर्ग का नाम आमतौर पर संक्षेप में दर्शाता है कि अपवाद क्यों हुआ:
FileNotFoundException
(फ़ाइल नहीं मिली)ArithmeticException
(गणितीय ऑपरेशन करते समय एक अपवाद हुआ)ArrayIndexOutOfBoundsException
(सूचकांक सरणी की सीमा से परे है)। उदाहरण के लिए, यह अपवाद तब होता है जब आप किसी सरणी की स्थिति 23 प्रदर्शित करने का प्रयास करते हैं जिसमें केवल 10 तत्व होते हैं।
Exception in thread "main"
उह्ह्ह। :/ यह ज्यादा मदद नहीं करता है। यह स्पष्ट नहीं है कि त्रुटि का क्या अर्थ है या यह कहां से आई है। यहां कोई उपयोगी जानकारी नहीं है। लेकिन जावा में बड़ी संख्या में अपवाद वर्ग प्रोग्रामर को वह देता है जो सबसे ज्यादा मायने रखता है: त्रुटि का प्रकार और इसका संभावित कारण (कक्षा के नाम में एम्बेडेड)। यह देखना बिलकुल दूसरी बात है
Exception in thread "main" java.io.FileNotFoundException: C:\Users\Username\Desktop\test.txt (The system cannot find the specified path)
यह तुरंत स्पष्ट हो जाता है कि समस्या क्या हो सकती है और समस्या को हल करने के लिए खुदाई कहाँ से शुरू करें! अपवाद, किसी भी वर्ग के उदाहरणों की तरह, वस्तुएँ हैं।
अपवादों को पकड़ना और संभालना
अपवादों के साथ काम करने के लिए जावा में कोड के विशेष ब्लॉक हैं:try
, catch
और finally
। कोड जहां प्रोग्रामर का मानना है कि अपवाद हो सकता है, try
ब्लॉक में रखा गया है। इसका मतलब यह नहीं है कि यहां अपवाद होगा। इसका मतलब है कि यह यहाँ हो सकता है, और प्रोग्रामर इस संभावना से अवगत है। आप जिस प्रकार की त्रुटि होने की उम्मीद करते हैं, उसे catch
ब्लॉक में रखा गया है। इसमें वे सभी कोड भी शामिल हैं जिन्हें अपवाद होने पर निष्पादित किया जाना चाहिए। यहाँ एक उदाहरण है:
public static void main(String[] args) throws IOException {
try {
BufferedReader reader = new BufferedReader(new FileReader("C:\\Users\\Username\\Desktop\\test.txt"));
String firstString = reader.readLine();
System.out.println(firstString);
} catch (FileNotFoundException e) {
System.out.println("Error! File not found!");
}
}
आउटपुट: त्रुटि! फ़ाइल प्राप्त नहीं हुई! हमने अपना कोड दो ब्लॉक में रखा है। पहले ब्लॉक में, हम अनुमान लगाते हैं कि "फ़ाइल नहीं मिली" त्रुटि हो सकती है। यह try
ब्लॉक है। दूसरे में, हम प्रोग्राम को बताते हैं कि त्रुटि होने पर क्या करना है। और विशिष्ट त्रुटि प्रकार: FileNotFoundException
. यदि हम ब्लॉक के कोष्ठकों में एक अलग अपवाद वर्ग रखते हैं catch
, तो FileNotFoundException
पकड़ा नहीं जाएगा।
public static void main(String[] args) throws IOException {
try {
BufferedReader reader = new BufferedReader(new FileReader("C:\\Users\\Username\\Desktop\\test.txt"));
String firstString = reader.readLine();
System.out.println(firstString);
} catch (ArithmeticException e) {
System.out.println("Error! File not found!");
}
}
आउटपुट: थ्रेड में अपवाद "मुख्य" java.io.FileNotFoundException: C:\Users\Username\Desktop\test.txt (सिस्टम निर्दिष्ट पथ नहीं ढूंढ सकता) ब्लॉक में कोड catch
नहीं चला, क्योंकि हमने "कॉन्फ़िगर" किया इस ब्लॉक को पकड़ने के लिए ArithmeticException
, और ब्लॉक में कोड ने try
एक अलग प्रकार फेंक दिया FileNotFoundException
:। हमने हैंडल करने के लिए कोई कोड नहीं लिखा है FileNotFoundException
, इसलिए प्रोग्राम के लिए डिफ़ॉल्ट जानकारी प्रदर्शित करता है FileNotFoundException
। यहां आपको तीन बातों पर ध्यान देने की जरूरत है। नंबर एक। एक बार ब्लॉक में किसी लाइन पर अपवाद होने पर try
, उसके बाद आने वाले कोड को निष्पादित नहीं किया जाएगा। कार्यक्रम का निष्पादन तुरंत catch
ब्लॉक में "कूदता है"। उदाहरण के लिए:
public static void main(String[] args) {
try {
System.out.println("Divide by zero");
System.out.println(366/0);// This line of code will throw an exception
System.out.println("This");
System.out.println("code");
System.out.println("will not");
System.out.println("be");
System.out.println("executed!");
} catch (ArithmeticException e) {
System.out.println("The program jumped to the catch block!");
System.out.println("Error! You can't divide by zero!");
}
}
आउटपुट: शून्य से विभाजित करें प्रोग्राम सीधे कैच ब्लॉक में चला गया! गलती! आप शून्य से विभाजित नहीं कर सकते! ब्लॉक की दूसरी लाइन पर try
, हम 0 से विभाजित करने का प्रयास करते हैं, जिसके परिणामस्वरूप एक ArithmeticException
. नतीजतन, ब्लॉक की 3-9 लाइनें try
निष्पादित नहीं की जाएंगी। जैसा कि हमने कहा, प्रोग्राम तुरंत catch
ब्लॉक को क्रियान्वित करना शुरू कर देता है। नंबर दो। कई catch
ब्लॉक हो सकते हैं। यदि ब्लॉक में कोड try
एक नहीं, बल्कि कई अलग-अलग प्रकार के अपवाद फेंक सकता है, तो आप catch
उनमें से प्रत्येक के लिए एक ब्लॉक लिख सकते हैं।
public static void main(String[] args) throws IOException {
try {
BufferedReader reader = new BufferedReader(new FileReader("C:\\Users\\Username\\Desktop\\test.txt"));
System.out.println(366/0);
String firstString = reader.readLine();
System.out.println(firstString);
} catch (FileNotFoundException e) {
System.out.println("Error! File not found!");
} catch (ArithmeticException e) {
System.out.println("Error! Division by 0!");
}
}
इस उदाहरण में, हमने दो catch
ब्लॉक लिखे हैं। यदि a ब्लॉक FileNotFoundException
में होता है try
, तो पहले catch
ब्लॉक को निष्पादित किया जाएगा। यदि कोई ArithmeticException
होता है, तो दूसरा ब्लॉक निष्पादित किया जाएगा। catch
आप चाहें तो 50 ब्लॉक लिख सकते हैं । बेशक, कोड नहीं लिखना बेहतर है जो 50 विभिन्न प्रकार के अपवादों को फेंक सकता है। :) तीसरा। आप कैसे जानते हैं कि आपका कोड कौन से अपवाद फेंक सकता है? ठीक है, आप उनमें से कुछ का अनुमान लगाने में सक्षम हो सकते हैं, लेकिन आपके लिए सब कुछ अपने दिमाग में रखना असंभव है। जावा कंपाइलर इसलिए सबसे आम अपवादों और उन स्थितियों को जानता है जहां वे हो सकते हैं। उदाहरण के लिए, यदि आप कोड लिखते हैं कि संकलक जानता है कि दो प्रकार के अपवाद हो सकते हैं, तो आपका कोड तब तक संकलित नहीं होगा जब तक आप उन्हें संभाल नहीं लेते। इसके उदाहरण हम नीचे देखेंगे। अब अपवाद प्रबंधन के बारे में कुछ शब्द। अपवादों को संभालने के 2 तरीके हैं। हम पहले से ही पहले का सामना कर चुके हैं: विधि अपवाद को catch()
ब्लॉक में ही संभाल सकती है। एक दूसरा विकल्प है: विधि कॉल स्टैक के अपवाद को फिर से फेंक सकती है। इसका क्या मतलब है? उदाहरण के लिए, हमारे पास एक ही printFirstString()
विधि वाला एक वर्ग है, जो एक फ़ाइल पढ़ता है और इसकी पहली पंक्ति प्रदर्शित करता है:
public static void printFirstString(String filePath) {
BufferedReader reader = new BufferedReader(new FileReader(filePath));
String firstString = reader.readLine();
System.out.println(firstString);
}
वर्तमान में, हमारा कोड संकलित नहीं होता है, क्योंकि इसमें बिना क्रिया के अपवाद हैं। पंक्ति 1 में, आप फ़ाइल का पथ निर्दिष्ट करते हैं। कंपाइलर जानता है कि ऐसा कोड आसानी से एक FileNotFoundException
. पंक्ति 3 में, आप फ़ाइल से पाठ पढ़ते हैं। इस प्रक्रिया का परिणाम आसानी से IOException
(इनपुट/आउटपुट त्रुटि) हो सकता है। अब कंपाइलर आपसे कहता है, "दोस्त, मैं इस कोड को स्वीकार नहीं करूंगा और मैं इसे तब तक कंपाइल नहीं करूंगा जब तक कि आप मुझे यह न बताएं कि अगर इन अपवादों में से एक होता है तो मुझे क्या करना चाहिए। और वे आपके द्वारा लिखे गए कोड के आधार पर निश्चित रूप से हो सकते हैं।" !" इससे बचने का कोई रास्ता नहीं है: आपको दोनों को संभालना होगा! हम पहले अपवाद से निपटने के तरीके के बारे में पहले से ही जानते हैं: हमें अपना कोड एक try
ब्लॉक में रखना होगा और दो catch
ब्लॉक जोड़ना होगा:
public static void printFirstString(String filePath) {
try {
BufferedReader reader = new BufferedReader(new FileReader(filePath));
String firstString = reader.readLine();
System.out.println(firstString);
} catch (FileNotFoundException e) {
System.out.println("Error, file not found!");
e.printStackTrace();
} catch (IOException e) {
System.out.println("File input/output error!");
e.printStackTrace();
}
}
लेकिन यही एकमात्र विकल्प नहीं है। हम विधि के अंदर एरर-हैंडलिंग कोड लिखने के बजाय केवल अपवाद को ऊपर फेंक सकते हैं। throws
यह विधि घोषणा में कीवर्ड का उपयोग करके किया जाता है :
public static void printFirstString(String filePath) throws FileNotFoundException, IOException {
BufferedReader reader = new BufferedReader(new FileReader(filePath));
String firstString = reader.readLine();
System.out.println(firstString);
}
कीवर्ड के बाद throws
, हम सभी प्रकार के अपवादों की अल्पविराम से अलग की गई सूची का संकेत देते हैं जो विधि फेंक सकती है। क्यों? अब, अगर कोई printFirstString()
प्रोग्राम में विधि को कॉल करना चाहता है, तो उसे (आपको नहीं) अपवाद प्रबंधन लागू करना होगा। उदाहरण के लिए, मान लीजिए कि प्रोग्राम में कहीं और आपके किसी सहकर्मी ने एक विधि लिखी है जो आपकी printFirstString()
पद्धति को कॉल करती है:
public static void yourColleagueMethod() {
// Your colleague's method does something
//...and then calls your printFirstString() method with the file it needs
printFirstString("C:\\Users\\Henry\\Desktop\\testFile.txt");
}
हमें त्रुटि मिलती है! यह कोड संकलित नहीं होगा! printFirstString()
हमने विधि में अपवाद-हैंडलिंग कोड नहीं लिखा । नतीजतन, यह कार्य अब विधि का उपयोग करने वालों के कंधों पर पड़ता है। दूसरे शब्दों में, methodWrittenByYourColleague()
विधि में अब समान 2 विकल्प हैं: इसे या तो try-catch
दोनों अपवादों को संभालने के लिए एक ब्लॉक का उपयोग करना चाहिए, या उन्हें फिर से फेंकना चाहिए।
public static void yourColleagueMethod() throws FileNotFoundException, IOException {
// The method does something
//...and then calls your printFirstString() method with the file it needs
printFirstString("C:\\Users\\Henry\\Desktop\\testFile.txt");
}
दूसरे मामले में, कॉल स्टैक में अगली विधि- एक कॉलिंग- को methodWrittenByYourColleague()
अपवादों को संभालना होगा। इसलिए हम इसे "अपवाद को फेंकना या पास करना" कहते हैं। यदि आप कीवर्ड का उपयोग करके अपवादों को ऊपर की ओर फेंकते हैं throws
, तो आपका कोड संकलित हो जाएगा। इस बिंदु पर, ऐसा लगता है कि संकलक कह रहा है, "ठीक है, ठीक है। आपके कोड में संभावित अपवादों का एक समूह है, लेकिन मैं इसे संकलित करूँगा। लेकिन हम इस वार्तालाप पर वापस आएँगे!" और जब आप किसी ऐसी विधि को कॉल करते हैं जिसमें बिना क्रिया के अपवाद होते हैं, तो संकलक अपना वादा पूरा करता है और आपको उनके बारे में फिर से याद दिलाता है। अंत में, हम finally
ब्लॉक के बारे में बात करेंगे (यमक के लिए खेद है)। try-catch-finally
यह ट्राइमुविरेट को संभालने वाले अपवाद का अंतिम भाग है ।.
public static void main(String[] args) throws IOException {
try {
BufferedReader reader = new BufferedReader(new FileReader("C:\\Users\\Username\\Desktop\\test.txt"));
String firstString = reader.readLine();
System.out.println(firstString);
} catch (FileNotFoundException e) {
System.out.println("Error! File not found!");
e.printStackTrace();
} finally {
System.out.println ("And here's the finally block!");
}
}
इस उदाहरण में, ब्लॉक के अंदर का कोड finally
दोनों मामलों में निष्पादित किया जाएगा। यदि ब्लॉक में कोड try
बिना किसी अपवाद के पूर्ण रूप से चलता है, तो finally
ब्लॉक अंत में चलेगा। यदि ब्लॉक के अंदर का कोड try
एक अपवाद से बाधित होता है और प्रोग्राम catch
ब्लॉक पर कूद जाता है, तो ब्लॉक के अंदर कोड finally
के बाद भी ब्लॉक चलेगा । यह क्यों आवश्यक है? इसका मुख्य उद्देश्य अनिवार्य कोड निष्पादित करना है: कोड जिसे परिस्थितियों की परवाह किए बिना निष्पादित किया जाना चाहिए। उदाहरण के लिए, यह अक्सर प्रोग्राम द्वारा उपयोग किए जाने वाले कुछ संसाधनों को मुक्त कर देता है। हमारे कोड में, हम फ़ाइल से जानकारी पढ़ने और ऑब्जेक्ट को पास करने के लिए एक स्ट्रीम खोलते हैं । catch
BufferedReader
हमें अपने पाठक को बंद करना चाहिए और संसाधनों को जारी करना चाहिए। यह किया जाना चाहिए इससे कोई फर्क नहीं पड़ता कि कार्यक्रम कब काम करता है, और जब यह अपवाद फेंकता है। ऐसा करने के लिए ब्लॉक finally
एक बहुत ही सुविधाजनक स्थान है:
public static void main(String[] args) throws IOException {
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader("C:\\Users\\Username\\Desktop\\test.txt"));
String firstString = reader.readLine();
System.out.println(firstString);
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
System.out.println ("And here's the finally block!");
if (reader != null) {
reader.close();
}
}
}
अब हम निश्चिंत हैं कि हम संसाधनों का ध्यान रखेंगे, भले ही कार्यक्रम चल रहा हो तो क्या होता है। :) अपवादों के बारे में आपको केवल इतना ही जानने की आवश्यकता नहीं है। प्रोग्रामिंग में एरर हैंडलिंग एक सुपर महत्वपूर्ण विषय है। इसके लिए बहुत सारे लेख समर्पित हैं। अगले पाठ में, हम पता लगाएंगे कि किस प्रकार के अपवाद हैं और अपने स्वयं के अपवाद कैसे बनाएं। :) तब आप देखना!
GO TO FULL VERSION