التسلسل الهرمي لفئات الاستثناءات
جزء من قسم البرمجة كائنية التوجه في رحلة Java على Coddy. الدرس 59 من 87.
يعتمد نظام معالجة الاستثناءات في Java على تسلسل هرمي منظّم جيدًا للفئات، ويقع في جذره الصنف Throwable. يساعدك فهم هذا التسلسل الهرمي على التقاط الاستثناءات ومعالجتها بفعالية أكبر.
في القمة يوجد Throwable، وهو الأصل لجميع الاستثناءات والأخطاء. وله فئتان فرعيتان مباشرتان:
Throwable
├── Error // مشكلات خطيرة (لا تلتقط هذه)
└── Exception // مشكلات يمكن التعافي منها
└── RuntimeException // استثناءات غير مفحوصةالخطأ يمثّل مشكلات خطيرة لا ينبغي للتطبيقات أن تحاول معالجتها، مثل OutOfMemoryError أو StackOverflowError. وتشير هذه المشكلات إلى مشكلات أساسية في JVM نفسه.
Exception هو الفرع الذي ستتعامل معه غالبًا. وينقسم إلى فئتين: checked exceptions (الفئات الفرعية المباشرة من Exception) وunchecked exceptions (الفئات الفرعية من RuntimeException).
// فئات الاستثناءات الشائعة
Exception
├── IOException // مشاكل الملفات/الشبكة
├── SQLException // مشاكل قواعد البيانات
└── RuntimeException
├── NullPointerException
├── ArrayIndexOutOfBoundsException
└── IllegalArgumentExceptionلأن exceptions هي classes، فإنها تتبع قواعد الوراثة. عندما تستخدم catch مع نوع exception أب، فإنك تلتقط أيضًا جميع أبنائه:
try {
// بعض الكود
} catch (Exception e) {
// يلتقط جميع الاستثناءات (واسع جدًا عادةً)
}try {
// بعض الكود
} catch (RuntimeException e) {
// Catches only runtime exceptions and subclasses
}يتيح لك هذا التسلسل الهرمي أن تكون محددًا أو عامًا بالقدر اللازم عند معالجة الأخطاء، وهو الأساس لإنشاء الاستثناءات المخصصة الخاصة بك.
التحدي
سهللنَبْنِ محللًا للاستثناءات يوضّح كيفية عمل التسلسل الهرمي للاستثناءات في Java عمليًا! ستنشئ نظامًا يلتقط الاستثناءات عند مستويات مختلفة من التخصيص ويُبلغ عن النوع الذي تم التقاطه.
ستنظّم شيفرتك عبر ثلاثة ملفات:
ExceptionThrower.java: أنشئ فئة يمكنها تشغيل أنواع مختلفة من الاستثناءات استنادًا إلى الإدخال. يجب أن تحتوي فئتك على ثلاث دوال static:triggerRuntime(String type)- استنادًا إلى سلسلة النوع، اطرح استثناءات runtime مختلفة:- إذا كان type هو
"null"، فاطرحNullPointerExceptionمع الرسالة"Null value encountered" - إذا كان type هو
"index"، فاطرحArrayIndexOutOfBoundsExceptionمع الرسالة"Invalid index" - إذا كان type هو
"argument"، فاطرحIllegalArgumentExceptionمع الرسالة"Bad argument"
triggerArithmetic()- اطرحArithmeticExceptionمع الرسالة"Division error"triggerGeneric()- اطرحIllegalStateExceptionمع الرسالة"Generic runtime error"(تسلسله الهرمي هو Exception > RuntimeException > IllegalStateException)- إذا كان type هو
ExceptionAnalyzer.java: أنشئ فئة تلتقط الاستثناءات عند مستويات مختلفة من التسلسل الهرمي وتحدّد ما تم التقاطه. ضمّن هذه الدوال static:analyzeSpecific(String type)- استدعِExceptionThrower.triggerRuntime(type)داخل كتلة try. استخدم كتل catch منفصلة لكل منNullPointerExceptionوArrayIndexOutOfBoundsExceptionوIllegalArgumentException. لكل منها، اطبع:Caught specific: [exception class simple name]متبوعًا بـMessage: [exception message]analyzeWithParent()- استدعِExceptionThrower.triggerArithmetic()داخل كتلة try. التقطه باستخدامRuntimeException(نوعه الأب). اطبع:Caught via parent: RuntimeExceptionمتبوعًا بـActual type: [exception class simple name]analyzeWithGrandparent()- استدعِExceptionThrower.triggerGeneric()داخل كتلة try. التقطه باستخدامException(وهو أعلى في التسلسل الهرمي). اطبع:Caught via grandparent: Exceptionمتبوعًا بـActual type: [exception class simple name]Main.java: اجمع محلل الاستثناءات معًا! ستتلقى إدخالًا واحدًا: سلسلة نوع الاستثناء (إما"null"أو"index"أو"argument").أولًا، اطبع
=== Specific Catch ===واستدعِanalyzeSpecificباستخدام إدخالك.ثم اطبع سطرًا فارغًا، و
=== Parent Catch ===، واستدعِanalyzeWithParent.أخيرًا، اطبع سطرًا فارغًا، و
=== Grandparent Catch ===، واستدعِanalyzeWithGrandparent.
ستتلقى إدخالًا واحدًا: نوع الاستثناء المطلوب تشغيله ("null" أو "index" أو "argument").
استخدم e.getClass().getSimpleName() للحصول على اسم فئة الاستثناء، واستخدم e.getMessage() لاسترداد رسالته. يوضّح هذا التحدي كيف يؤدي التقاط نوع استثناء أب إلى التقاط جميع الأنواع الفرعية التابعة له أيضًا: وهو مفهوم أساسي عند تحديد مدى تخصيص معالجة الاستثناءات!
جرّب بنفسك
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String type = scanner.nextLine();
// TODO: Print "=== Specific Catch ===" and call ExceptionAnalyzer.analyzeSpecific(type)
// TODO: اطبع سطرًا فارغًا، ثم "=== Parent Catch ==="، ثم استدعِ ExceptionAnalyzer.analyzeWithParent()
// TODO: Print a blank line, then "=== Grandparent Catch ===", then call ExceptionAnalyzer.analyzeWithGrandparent()
}
}
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس البرمجة كائنية التوجه
1أساسيات الـ OOP
الملفات الخارجيةمقدمة في الـ OOPالفئات (Classes) مقابل الكائنات (Objects)الكلمة المفتاحية thisالدوال (Methods)الحقول (Attributes)دالة البناء (Constructor)تعدد أشكال دالة البناء (Constructor Overloading)مراجعة - آلة حاسبة بسيطة4الوراثة
الوراثة الأساسية (extends)الكلمة المفتاحية superإعادة تعريف الدوال (@Override)تسلسل المنشئات (Constructor Chaining)كلاس Objectالوراثة الأحادية ومتعددة المستوياتلماذا لا توجد وراثة متعددة للكلاساتمراجعة - هيكلية الموظفين7الدوال الخاصة وفئة Object
دالة toString()equals() و hashCode()دالة clone()compareTo() و Comparableواجهة Comparatorمراجعة - الترتيب المخصص10معالجة الاستثناءات في OOP
التسلسل الهرمي لفئات الاستثناءاتالاستثناءات المخصصةالأخطاء من نوع Checked مقابل Uncheckedنمط Try With Resourcesمراجعة - Validated User2محددات الوصول والتغليف
نظرة عامة على مستويات الوصولدوال Getter و Setterإخفاء البياناتالكلمة المفتاحية finalمراجعة - مدير الحساب البنكي5تعدد الأشكال (Polymorphism)
أساسيات الـ Method Overloadingالـ Method Overriding (في وقت التشغيل)الـ Upcasting والـ Downcastingمعامل الـ instanceofالفئات والدوال المجردة (Abstract)مراجعة - حاسبة الأشكال8مفاهيم OOP المتقدمة
الـ Composition مقابل الـ Inheritanceالـ Aggregation مقابل الـ Compositionالفئات الداخلية والمتداخلة والمجهولة (Inner, Nested & Anonymous)الـ Enums ودوالهاالـ Records (Java 16+)الـ Sealed Classes (Java 17+)11أنماط التصميم - الجزء الأول
مقدمة في أنماط التصميمنمط Singletonنمط Factoryنمط Builderنمط Observerنمط Strategy3خصائص الفئة والعضو الساكن
المتغيرات الخاصة بالكائن مقابل المتغيرات الساكنةالدوال الساكنةالكتل البرمجية الساكنةالثوابت (static final)ملخص - العداد والأدوات المساعدة6الواجهات (Interfaces) والأصناف المجردة (Abstract Classes)
مقدمة في الواجهات (Interfaces)تنفيذ الواجهات (Interfaces)تنفيذ واجهات متعددةالـ Default و Static في الواجهاتالأصناف المجردة مقابل الواجهاتالواجهات الوظيفية (Functional Interfaces)مراجعة - نظام الدفع9الأنواع العامة (Generics)
مقدمة في الأنواع العامةالأصناف العامة (Generic Classes)الدوال العامة (Generic Methods)معاملات الأنواع المقيدةالرموز البديلة (?, extends, super)مراجعة - الحاويات العامة12أنماط التصميم - الجزء الثاني
نمط الأمرنمط المحولنمط المزيننمط طريقة القالبنمط الحالةنمط التركيبنمط المكررتدرّب بنفسك: مترجم Java عبر الإنترنت