السلام عليكم ورحمة الله وبركاته..
في رأيي المتواضع ان أفضل وسيلة لفهم أوامر الـ try والـ catch هي أن نحاول قبلاً أن نستوعب الـ Exceptions بشكل تام.
إعلان حالة الطوارئ (throws) هي الوسيلة التي تستخدمها الآلة التخيلية في الجافا للإعلان عن وجود مشكلة أو خطأ في تشغيل البرنامج
فمثلاً حين تحدث مشكلة ما لا تستطيع الآلة التخيلية التعامل معها لذا توقف عمل البرنامج تماماً (بشكل غير لائق بالنسبة للمبرمج طبعاً) وتعلن المشكلة التي واجهتها بأن تقوم بعملية throw (بالعربي قذف أو إلقاء) لهذه المشكلة.
في الحقيقة الآلة التخيلية تقوم بالإعلان عن نوعين من الأخطاء أو المشاكل، Errors وهي الأخطاء التي لا حيلة للمبرمج في التعامل معها (مثلاً أن ينقطع التيار الكهربائي) والنوع الثاني هو الـ Exceptions وهي الأخطاء التي يمكن أن يتوقعها المبرمج ولديه الوسيلة للتعامل معها.
إذاً لننسَ الـ Errors ونحاول التركيز على الـ Exceptions.
حتى نفهم خطورة الexceptions وفائدتها في الوقت ذاته.. دعوني أستخدم مثالي المفضل.. الكرة
لنتخيل أن الآلة التخيلية حين تواجه مشكلة تضعها في كرة زجاجية وتقذف الكرة في الهواء..
ماذا سيحدث؟.. سترتفع الكرة في الهواء.. ثم سترتد إلى الأرض يفعل الجاذبية.. حتى.. هممم حتى ترتطم بالأرض وتتفتت إلى قطع صغيرة وهذا يعني أن البرنامج سيتوقف تماماً عن العمل!
ما الحل في رأيكم؟ أليس لطيفاً لو كان لدينا في البرنامج وسيلة لالتقاط الكرة بالسلامة قبل أن تتكسر على الأرض؟
لنأخذ هذا المثال البسيط.
في السطر الأول أنشأت متغير من نوع نصي ووضعت فيه القيمة x
في السطر الثاني أنشأت متغير من نوع رقم صحيح وقرأت القيمة الرقمية من المتغير النصي. طبعاً في الحالات العادية من المفترض أن تكون القيمة الموجودة في النص رقم.. مثلاً "123" ولكن في حالتنا كانت حرف وليس رقماً.. لذا عملية القراءة ستسبب حدوث exception كما يلي:
ما حدث في هذه الحالة نسميه Exception. وما ترونه في الصورة الأخيرة هي وسيلة الآلة التخيلية لإخبارنا أنها واجهت مشكلة، ولا تعرف كيف يمكن أن تحلها. وفي الحقيقة في الصورة ستجدون اسم الـ Exception وهو: NumberFormatException.
وهذا هو في الواقع اسم كرتنا الزجاجية التي سيلقيها البرنامج في حال فشل في قراءة رقم من النص.
طبعاً في مثالنا البسيط، تعمّدتُ وضع قيمة نصية في المتغير النصي.. وهذا يعني أن هناك دائماً مجال لأن يقوم شخص ما بإدخال قيم خاطئة، وهذا يعني أننا يجب أن نكون حذرين نوعاً في التعامل مع أنواع المدخلات.
كيف نحل ذلك؟ ما رأيكم في هذا السيناريو:
سنحاول قراءة قيمة رقمية صحيحة عن طريقة Integer.parseInt من المتغير النصي str..
إذا فشلنا وألقت الآلة التخيلية بالاستثناء NumberFormatException سنكون مستعدين وسنلتقطه، ثم نتعامل معه.
ها قد وصلنا أخيراً إلى سؤال الأخ الفاضل فتى الذهب.. كيف أستخدم التراي والكاتش..
؟؟
try & catch نستخدمهم في حالة كانت لدينا وظيفة method من المحتمل أن تقذف exception.
هكذا:
الآن القسم الأول (try) نحاول أن نجرب فيه شيئاً ما.. في حالتنا نحاول قراءة رقم من متغير نصي.. لنفترض أن المحاولة فشلت.. وألقى البرنامج exception في هذه الحالة سيتحول الموضوع إلى ال catch..
ونلاحظ أننا بين قوسين بعد كلمة catch مباشرة حددنا نوع الاكسبشن الذي سنلتقطه.. إذا وضعنا Exception فقط.. فإنه سيلتقط أي نوع من الاستثناءات بدون تحديدها (فجميع الاستثناءات تكون فئة مستمدة من فئة Excetption).
في داخل الكاتش نستطيع أن نحدد ماذا سنفعل في حالة حدوث الخطأ أو المشكلة..
ويمكننا أن يكون في جزء الـ try أكثر من statement تسبب كل منها exception مختلف، وهكذا يمكن أن يكون لدينا أكثر من catch بحيث يتكفّل كل منها بـ exception مختلف، ومن الممكن أيضاً استخدام جزء أخير finally بحيث يلتقط أي exception آخر، هكذا:
لو أنني غطيتُ الـ throw و الـ throws أيضاً.. سأحاول تغطيتهما في وقت لاحق.. ولكن أتصور أنه يمكنك أن تفتح الباب لفهمهما الآن..
يمكنك دائماً أن تقوم بتعريف الاستثناءات الخاصة بك بحيث تكون extends Exception لتتعامل مع الاستثناءات الخاصة ببرامجك (فإذا كان لديك مثلاً كلاس للخط المرسوم على الشاشة، فأتصور سيكون مفيداً لو وضعت في اعتبارك أنه يمكن أن يحاول المستخدم رسم الخط خارج حدود الرسم وعملت الاستثناء المناسب)
بالمناسبة Exception كلاس موجود في java.lang ولا تحتاج لعمل أي import
سأبذل جهدي للإجابة عن أي سؤال من واقع الخبرة أو من المراجع إن شاء الله، فلا تتردد في طرح أي استفسار..
تحياتي
وفوق كل ذي علم عليم