JavaRush /جاوا بلاگ /Random-UR /جاوا میں مستثنیات: پکڑنا اور سنبھالنا

جاوا میں مستثنیات: پکڑنا اور سنبھالنا

گروپ میں شائع ہوا۔
ہیلو! مجھے آپ کے سامنے اسے توڑنے سے نفرت ہے، لیکن پروگرامر کے کام کا ایک بہت بڑا حصہ غلطیوں سے نمٹنا ہے۔ اور اکثر - ان کے اپنے ساتھ. ایسا ہوتا ہے کہ کوئی بھی لوگ ایسے نہیں ہوتے جو غلطیاں نہ کرتے ہوں۔ اور اس طرح کے کوئی پروگرام بھی نہیں ہیں۔ یقینا، ایک غلطی پر کام کرتے وقت اہم چیز اس کی وجہ کو سمجھنا ہے. اور پروگرام میں اس طرح کی وجوہات کا ایک پورا گروپ ہوسکتا ہے۔ ایک موقع پر، جاوا کے تخلیق کاروں کو ایک سوال کا سامنا کرنا پڑا: پروگراموں میں ان ممکنہ غلطیوں کا کیا کریں؟ ان سے مکمل پرہیز کرنا غیر حقیقی ہے۔ پروگرامرز کچھ ایسا لکھ سکتے ہیں جس کا تصور کرنا بھی ناممکن ہے :) اس کا مطلب یہ ہے کہ زبان میں غلطیوں سے نمٹنے کے لیے ایک طریقہ کار بنانا ضروری ہے۔ دوسرے الفاظ میں، اگر پروگرام میں کچھ خرابی واقع ہوئی ہے تو، مزید کام کے لئے ایک سکرپٹ کی ضرورت ہے. جب کوئی غلطی ہوتی ہے تو پروگرام کو بالکل کیا کرنا چاہئے؟ آج ہم اس طریقہ کار سے واقف ہوں گے۔ اور اسے "استثنیات " کہا جاتا ہے ۔

جاوا میں کیا استثناء ہے؟

ایک استثناء کچھ غیر معمولی، غیر منصوبہ بند صورت حال ہے جو پروگرام کے آپریشن کے دوران واقع ہوئی ہے۔ جاوا میں مستثنیات کی بہت سی مثالیں ہوسکتی ہیں۔ مثال کے طور پر، آپ نے ایک کوڈ لکھا ہے جو فائل سے متن پڑھتا ہے اور کنسول میں پہلی لائن دکھاتا ہے۔
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. نتیجہ:

Exception in thread "main" java.io.FileNotFoundException: C:\Users\Username\Desktop\test.txt (Системе не удается найти указанный путь)
ہر استثناء کی نمائندگی جاوا میں ایک الگ کلاس کے ذریعہ کی جاتی ہے۔ تمام استثنائی کلاسیں ایک مشترکہ "آباؤ اجداد" سے آتی ہیں - پیرنٹ کلاس Throwable۔ استثنائی طبقے کا نام عام طور پر اس کی موجودگی کی وجہ کو مختصراً ظاہر کرتا ہے:
  • FileNotFoundException(فائل نہیں ملی)
  • ArithmeticException(ریاضی کا آپریشن کرتے وقت استثناء)
  • ArrayIndexOutOfBoundsException(سرنی سیل کی تعداد اس کی لمبائی سے باہر بیان کی گئی ہے)۔ مثال کے طور پر، اگر آپ سیل سرنی[23] کو کنسول میں 10 کی لمبائی والے سرنی کے لیے آؤٹ پٹ کرنے کی کوشش کرتے ہیں۔
جاوا میں تقریباً 400 ایسی کلاسیں ہیں! اتنے کیوں؟ خاص طور پر پروگرامرز کے لیے ان کے ساتھ کام کرنا زیادہ آسان بنانے کے لیے۔ تصور کریں: آپ نے ایک پروگرام لکھا، اور جب یہ چلتا ہے، تو یہ ایک استثناء پھینک دیتا ہے جو اس طرح لگتا ہے:
Exception in thread "main"
اوہ:/ کچھ بھی واضح نہیں ہے۔ یہ کس قسم کی خرابی ہے اور یہ کہاں سے آئی ہے یہ واضح نہیں ہے۔ کوئی مفید معلومات نہیں ہے۔ لیکن اس طرح کی مختلف کلاسوں کی بدولت، پروگرامر اپنے لیے اہم چیز حاصل کرتا ہے - غلطی کی قسم اور اس کی ممکنہ وجہ، جو کلاس کے نام میں موجود ہے۔ بہر حال ، کنسول میں دیکھنا بالکل مختلف چیز ہے:
Exception in thread "main" java.io.FileNotFoundException: C:\Users\Username\Desktop\test.txt (Системе не удается найти указанный путь)
یہ فوری طور پر واضح ہو جاتا ہے کہ مسئلہ کیا ہو سکتا ہے اور مسئلہ کو حل کرنے کے لیے "کس سمت میں کھودنا ہے"! مستثنیات، کلاسز کی کسی بھی مثال کی طرح، آبجیکٹ ہیں۔

مستثنیات کو پکڑنا اور ہینڈلنگ کرنا

جاوا میں مستثنیات کے ساتھ کام کرنے کے لیے، خاص کوڈ بلاکس ہیں: try, catchاور finally. مستثنیات: مداخلت اور پروسیسنگ - 2وہ کوڈ جس میں پروگرامر مستثنیات کی توقع کرتا ہے اسے بلاک میں رکھا جاتا ہے 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بلاک بریکٹ میں ایک اور استثنائی کلاس پاس کرتے ہیں، تو یہ پکڑا نہیں جائے گا۔
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!");
   }
}
نتیجہ:

Exception in thread "main" java.io.FileNotFoundException: C:\Users\Username\Desktop\test.txt (Системе не удается найти указанный путь)
بلاک میں موجود کوڈ catchنے کام نہیں کیا کیونکہ ہم نے اس بلاک کو انٹرسیپٹ کرنے کے لیے "کنفیگر" کیا تھا ArithmeticException، اور بلاک میں موجود کوڈ نے tryدوسری قسم کو باہر پھینک دیا تھا FileNotFoundException۔ ہم نے کے لیے اسکرپٹ نہیں لکھا FileNotFoundException، اس لیے پروگرام کنسول میں وہ معلومات دکھاتا ہے جو بطور ڈیفالٹ کے لیے ظاہر ہوتی ہے FileNotFoundException۔ یہاں آپ کو 3 چیزوں پر توجہ دینے کی ضرورت ہے۔ پہلا. جیسے ہی ٹرائی بلاک میں کوڈ کی کسی بھی لائن میں کوئی استثناء واقع ہوتا ہے، اس کے بعد کا کوڈ مزید عمل میں نہیں آئے گا۔ پروگرام پر عمل درآمد فوری طور پر بلاک پر "چھلانگ" جائے گا catch۔ مثال کے طور پر:
public static void main(String[] args) {
   try {
       System.out.println("Divide a number 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("Not");
       System.out.println("will");
       System.out.println("done!");

   } catch (ArithmeticException e) {

       System.out.println("The program jumped to the catch block!");
       System.out.println("Error! You can't divide by zero!");
   }
}
نتیجہ:

Делим число на ноль 
Программа перепрыгнула в блок catch! 
Ошибка! Нельзя делить на ноль! 
tryدوسری لائن کے بلاک میں ، ہم نے ایک عدد کو 0 سے تقسیم کرنے کی کوشش کی، جس کے نتیجے میں ایک استثناء ہوا ArithmeticException۔ اس کے بعد، بلاک کی 6-10 لائنوں پر 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۔ اگر، بلاک میں tryہوتا ہے FileNotFoundException، تو پہلا بلاک عمل میں لایا جائے گا catch۔ اگر ایسا ہوتا ہے تو ArithmeticException، دوسرے کو پھانسی دے دی جائے گی۔ آپ کم از کم 50 بلاکس لکھ سکتے ہیں catch۔ لیکن یقیناً، بہتر ہے کہ ایسا کوڈ نہ لکھیں جو 50 مختلف قسم کی غلطیاں پھینک سکتا ہے :) تیسرا۔ آپ کو کیسے پتہ چلے گا کہ آپ کا کوڈ کیا مستثنیات پھینک سکتا ہے؟ ٹھیک ہے، آپ یقیناً کچھ کے بارے میں اندازہ لگا سکتے ہیں، لیکن ہر چیز کو اپنے سر میں رکھنا ناممکن ہے۔ لہذا، جاوا کمپائلر سب سے عام مستثنیات کے بارے میں جانتا ہے اور جانتا ہے کہ وہ کن حالات میں ہو سکتے ہیں۔ مثال کے طور پر، اگر آپ نے کوڈ لکھا ہے اور مرتب کرنے والا جانتا ہے کہ اس کے آپریشن کے دوران 2 قسم کی مستثنیات ہو سکتی ہیں، تو آپ کا کوڈ اس وقت تک مرتب نہیں ہو گا جب تک کہ آپ انہیں ہینڈل نہیں کر لیتے۔ ہم ذیل میں اس کی مثالیں دیکھیں گے۔ اب استثنا ہینڈلنگ کے بارے میں۔ ان پر کارروائی کرنے کے 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اس عمل میں ، input-output (Input-Output) کے دوران غلطی آسانی سے ہو سکتی ہے ۔ اب مرتب کرنے والا آپ سے کہہ رہا ہے، "یار، میں اس کوڈ کو منظور نہیں کروں گا اور نہ ہی اسے مرتب کروں گا جب تک کہ آپ مجھے یہ نہ بتائیں کہ اگر ان میں سے کوئی ایک استثناء ہوتا ہے تو مجھے کیا کرنا چاہیے۔ اور وہ یقینی طور پر آپ کے لکھے ہوئے کوڈ کی بنیاد پر ہو سکتے ہیں! . جانے کے لئے کہیں نہیں ہے، آپ کو دونوں پر کارروائی کرنے کی ضرورت ہے! پروسیسنگ کا پہلا آپشن ہمارے لیے پہلے سے ہی واقف ہے: ہمیں اپنا کوڈ ایک بلاک میں رکھنا ہوگا 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("Error while inputting/outputting data from file!");
       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 at one moment calls your printFirstString() method with the file it needs
   printFirstString("C:\\Users\\Eugene\\Desktop\\testFile.txt");
}
خرابی، کوڈ مرتب نہیں ہوتا! ہم نے طریقہ کار میں printFirstString()غلطی سے نمٹنے والی اسکرپٹ نہیں لکھی ۔ لہذا، کام ان لوگوں کے کندھوں پر آتا ہے جو اس طریقہ کو استعمال کریں گے. یعنی، طریقہ کو yourColleagueMethod()اب انہی 2 اختیارات کا سامنا ہے: اسے یا تو ان دونوں استثناء پر کارروائی کرنی چاہیے جو اس پر "پہنچتے ہیں" استعمال کرتے ہوئے try-catch، یا انہیں آگے بھیج دیں۔
public static void yourColleagueMethod() throws FileNotFoundException, IOException {
   //...the method does something

   //...and at one moment calls your printFirstString() method with the file it needs
   printFirstString("C:\\Users\\Eugene\\Desktop\\testFile.txt");
}
دوسری صورت میں، پروسیسنگ اسٹیک پر اگلے طریقہ کار کے کندھوں پر گرے گی - وہ جو کال کرے گا yourColleagueMethod()۔ یہی وجہ ہے کہ اس طرح کے طریقہ کار کو "اوپر کی طرف ایک استثناء پھینکنا"، یا "اوپر کی طرف جانا" کہا جاتا ہے۔ جب آپ مستثنیات کو استعمال کرتے ہوئے پھینک دیتے ہیں 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 is the finally block!");
   }
}
اس مثال میں، بلاک کے اندر کا کوڈ finallyدونوں صورتوں میں عمل میں آتا ہے۔ اگر بلاک میں موجود کوڈ کو tryمکمل طور پر لاگو کیا جاتا ہے اور اس میں کوئی رعایت نہیں آتی ہے، تو بلاک آخر میں فائر ہو جائے گا finally۔ اگر اندر موجود کوڈ میں tryخلل پڑتا ہے اور پروگرام بلاک پر چھلانگ لگاتا ہے catch، اندر کا کوڈ مکمل ہونے کے بعد catch، بلاک کو پھر بھی منتخب کیا جائے گا finally۔ اس کی ضرورت کیوں ہے؟ اس کا بنیادی مقصد کوڈ کے مطلوبہ حصے پر عمل درآمد کرنا ہے۔ وہ حصہ جو حالات سے قطع نظر مکمل کیا جانا چاہیے۔ مثال کے طور پر، یہ اکثر پروگرام کے ذریعہ استعمال ہونے والے کچھ وسائل کو آزاد کرتا ہے۔ ہمارے کوڈ میں، ہم فائل سے معلومات کو پڑھنے کے لیے ایک سلسلہ کھولتے ہیں اور اسے ایک میں منتقل کرتے ہیں BufferedReader۔ ہمیں readerبند کرنے اور وسائل کو آزاد کرنے کی ضرورت ہے۔ یہ کسی بھی صورت میں ہونا چاہیے: اس سے کوئی فرق نہیں پڑتا کہ پروگرام توقع کے مطابق کام کرتا ہے یا استثناء دیتا ہے۔ یہ ایک بلاک میں کرنا آسان ہے 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 is the finally block!");
       if (reader != null) {
           reader.close();
       }
   }
}
اب ہمیں پورا یقین ہے کہ ہم نے زیر قبضہ وسائل کا خیال رکھا ہے، قطع نظر اس کے کہ پروگرام کے چلنے کے دوران کیا ہوتا ہے :) آپ کو مستثنیات کے بارے میں صرف اتنا ہی جاننے کی ضرورت ہے۔ پروگرامنگ میں ایرر ہینڈلنگ ایک بہت اہم موضوع ہے: ایک سے زیادہ آرٹیکل اس کے لیے وقف ہیں۔ اگلے سبق میں ہم سیکھیں گے کہ کس قسم کی مستثنیات ہیں اور اپنا استثناء کیسے بنایا جائے :) وہاں ملتے ہیں!
تبصرے
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION