تصف الأمثلة الموجودة في هذه المقالة استخدام معالجة استثناءات Java. شاركها مع الجميع لتكون مرجعا لك. التحليل المحدد هو كما يلي:
يمكن أن تساعدنا آلية معالجة الاستثناءات في Java في تجنب الأخطاء التي قد تحدث في البرنامج أو معالجتها، بحيث لا يتم إنهاء البرنامج بشكل غير متوقع عند مواجهة بعض الأخطاء القابلة للاسترداد، ولكن معالجة هذه الأخطاء، مما يجعلنا أيضًا أفضل في كتابة البرامج تحتاج إلى كتابة الكثير من التعليمات البرمجية للتحقق من ظروف الخطأ، مما يعزز إمكانية قراءة التعليمات البرمجية ومنطقها. في Java، يمثل الاستثناء كائن كيان غير صحيح.
يمكن تقسيم الاستثناءات إلى فئتين؛ إحداهما أخطاء خطيرة، مثل أخطاء الأجهزة، وعدم كفاية الذاكرة، وما إلى ذلك، والتي تتوافق مع فئة الخطأ وفئاتها الفرعية ضمن حزمة java.lang. عادةً لا يمكن استرداد هذا النوع من برامج الأخطاء بحد ذاته ويحتاج إلى مقاطعة تنفيذ البرنامج، أما النوع الآخر فهو الأخطاء غير الجسيمة، مثل قيام المستخدم بإدخال بيانات غير قانونية، أو القسمة على 0، وما إلى ذلك. وهي تتوافق مع فئة الاستثناء و استثناءاته في الحزمة java.lang، يمكن استرداد هذا النوع من الأخطاء بشكل عام دون التأثير على تشغيل البرنامج.
يمكننا استخدام الكلمات الأساسية للمحاولة والالتقاط والأخيرة للقبض على الاستثناءات.
1. حاول، قبض
ضع العبارات التي قد تسبب استثناءات في كتلة المحاولة{}، ثم التقطها في كتلة عبارة Catch{}. استثناء إذا قسمت على 0:
public class SimpleDemo { // عملية التقسيم public static int devision(int a,int b) { return a / b } public static void main(String[] args) { حاول { // 5 مقسومًا على 0 SimpleDemo.devision(5) ,0);نتيجة التنفيذ:
كما ترون، تتم طباعة Finish، مما يشير إلى أن البرنامج لم ينته بسبب خطأ القسمة على 0.
وفي الوقت نفسه، وجدنا أيضًا أن عبارة System.out.println ضمن SimpleDemo.devision() حيث حدث الاستثناء لم يتم تنفيذها. بمجرد حدوث استثناء، سيقفز البرنامج من موضع التنفيذ الحالي دون تنفيذ العبارات التالية للاستثناء.
2. أخيرا
سيتم تنفيذ العبارات الموجودة في الكتلة الأخيرة بغض النظر عما إذا كان هناك استثناء أم لا.
قد يتساءل شخص ما، نظرًا لأنه سيتم تنفيذ البيانات الموجودة في الكتلة الأخيرة بغض النظر عما إذا كان هناك استثناء، فما هو التأثير العملي لهذا أخيرًا؟ ألا أستطيع أن أكتبها مباشرة في الخارج دون أن أنتهي؟
كما في المثال أعلاه، نضيف إرجاعًا إلى كتلة عبارة الالتقاط:
public class SimpleDemo { // عملية القسمة public static int Division(int a,int b) { return a / b } public static void main(String[] args) { حاول { // 5 مقسومًا على 0 SimpleDemo.division(5; ,0); System.out.println("Exception"); } Catch (Exception e) { e.printStackTrace(); System.out.println("أخيرًا"); } System.out.println("Finish");في هذا الوقت، لا تتم طباعة النهاية خارج الكتلة الأخيرة، ولكن تتم طباعة النهاية داخل الكتلة الأخيرة.
أخيرًا مفيد جدًا في التطوير الفعلي. على سبيل المثال، إذا فتحنا قاعدة بيانات وحدث استثناء عند قراءة البيانات وكتابتها في قاعدة البيانات، فيجب علينا إغلاق اتصال قاعدة البيانات وتحرير الموارد المقابلة. في هذا الوقت، من الأنسب كتابة التعليمات البرمجية لتحرير الموارد في الكتلة النهائية.
ولكن تجدر الإشارة إلى أنه لن يتم تنفيذ الكتلة النهائية في حالة واحدة. إذا خرج البرنامج قبل تنفيذ الكتلة الأخيرة، مثل استدعاء الأسلوب System.exit()، فلن تحصل الكتلة الأخيرة على فرصة للتنفيذ.
3. رمي استثناء
إذا حدث استثناء في إحدى الطرق، ولكننا لا نريد معالجة الاستثناء مباشرة في الطريقة، ولكننا نريد أن يتعامل معه المتصل بالطريقة، فيمكننا استخدام الكلمة الأساسية throws للإعلان عن هذه الطريقة لطرح الاستثناء. هذا أمر شائع جدًا في وظائف واجهة برمجة التطبيقات التي توفرها Sun، على سبيل المثال، تم الإعلان عن طريقة القراءة في java.io.Reader لطرح IOException:
قراءة int العامة (char[] cbuf) تطرح IOException
في هذا الوقت، عندما نستدعي طريقة القراءة، يجب علينا وضعها في كتلة عبارة المحاولة للقبض على الاستثناءات، وإلا فإن المترجم سيبلغ عن خطأ ويجبرنا على التقاط الاستثناءات.
بالطبع، إذا كنا لا نريد حقًا التعامل مع الاستثناءات عند استدعاء القراءة، فيمكننا أيضًا الإعلان عن الطريقة التي تستدعي طريقة القراءة كطرح IOException، بحيث يتم طرح الاستثناء مرة أخرى. إذا أعلنا عن استثناء في الوظيفة الرئيسية، فسيتم في النهاية التقاط معلومات الاستثناء ومعالجتها بواسطة JVM، وتكون نتيجة معالجة JVM هي طباعة معلومات الاستثناء ثم إنهاء البرنامج.
4. هيكل معالجة الاستثناءات
جميع فئات الاستثناء مشتقة من فئة الاستثناء. هذا يعني أنه إذا لم نكن متأكدين من نوع الاستثناء الذي سيحدث، فيمكننا الإعلان مباشرة عن كائن استثناء في الالتقاط لالتقاط كافة استثناءات فئة الاستثناء وفئاتها الفرعية. ولكن انتبه إلى الترتيب الذي يتم به كتابة الصيد. إذا كان هناك العديد من عمليات الالتقاط بعد المحاولة وأعلنت عملية الالتقاط الأولى عن كائن استثناء، فستتم معالجة الاستثناء مباشرة من خلال عملية الالتقاط الأولى، ولن تتمكن عمليات الالتقاط اللاحقة من التقاط هذا الاستثناء. سيؤدي هذا النوع من الأخطاء إلى إنشاء خطأ أثناء التجميع. على سبيل المثال:
public class CatchDemo { // عملية القسمة public static int Division(int a,int b) { return a / b } public static void main(String[] args) {try { CatchDemo.division(4,0 } Catch (استثناء e) { System.out.println("فئة الاستثناء" } Catch(ArithmeticException e) { System.out.println("ArithmeticException Class"); } } }يُخرج المترجم أن ArithmeticException قد تم اكتشافه، مما يعني أن الاستثناء أعلاه قد اكتشف هذا الاستثناء وليست هناك حاجة للقبض عليه مرة أخرى.
ماذا سيحدث إذا تم عكس هذين المصيدين؟
public class CatchDemo { // عملية القسمة public static int Division(int a,int b) { return a / b } public static void main(String[] args) {try { CatchDemo.division(4,0 } Catch (ArithmeticException e) { System.out.println("ArithmeticException Class"); Catch(Exception e) { System.out.println("فئة الاستثناء"); } } }في هذا الوقت، وجدنا أن الكود اجتاز التجميع، وكانت نتيجة التنفيذ أن ArithmeticException اكتشف هذا الاستثناء، لكن الالتقاط اللاحق لم يلتقطه.
آمل أن تكون هذه المقالة مفيدة لبرمجة جافا للجميع.