Menu
Coddy logo textTech
flag Ar iconالعربيةdown icon

التسلسل الهرمي لفئات الاستثناءات

جزء من قسم Object Oriented Programming في رحلة Java على Coddy — الدرس 59 من 87.

نظام معالجة الاستثناءات في Java مبني على تسلسل هرمي منظم للفئات جذوره في فئة Throwable. يساعدك فهم هذا التسلسل الهرمي على التقاط ومعالجة الاستثناءات بشكل أكثر فعالية.

في القمة يقع Throwable، وهو الأب لجميع الاستثناءات والأخطاء. ولديه فئتان فرعيتان مباشرتان:

Throwable
├── Error          // مشاكل خطيرة (لا تقم بالتقاط هذه)
└── Exception      // مشاكل يمكن تداركها
    └── RuntimeException  // استثناءات غير مفحوصة

يمثل Error مشكلات خطيرة لا ينبغي للتطبيقات محاولة التعامل معها—مثل OutOfMemoryError أو StackOverflowError. تشير هذه إلى مشكلات أساسية في الـ JVM نفسها.

Exception هو الفرع الذي ستتعامل معه بشكل أكبر. وينقسم إلى فئتين: الاستثناءات المفحوصة (checked exceptions) (فئات فرعية مباشرة من Exception) والاستثناءات غير المفحوصة (unchecked exceptions) (فئات فرعية من RuntimeException).

// فئات الاستثناءات الشائعة
Exception
├── IOException           // مشاكل الملفات/الشبكة
├── SQLException          // مشاكل قاعدة البيانات
└── RuntimeException
    ├── NullPointerException
    ├── ArrayIndexOutOfBoundsException
    └── IllegalArgumentException

بما أن الاستثناءات هي فئات، فهي تتبع قواعد الوراثة. عندما تقوم بالتقاط نوع استثناء أب، فإنك تلتقط أيضاً جميع أبنائه:

try {
    // بعض التعليمات البرمجية
} catch (Exception e) {
    // يلتقط جميع الاستثناءات (واسع جداً عادةً)
}
try {
    // بعض الأكواد
} catch (RuntimeException e) {
    // يلتقط فقط استثناءات وقت التشغيل والفئات الفرعية
}

يتيح لك هذا التسلسل الهرمي أن تكون دقيقاً أو عاماً حسب الحاجة عند معالجة الأخطاء، وهو الأساس لإنشاء استثناءاتك المخصصة.

challenge icon

التحدي

سهل

لنقم ببناء محلل استثناءات (exception analyzer) يوضح كيفية عمل التسلسل الهرمي للاستثناءات في Java من الناحية العملية! ستقوم بإنشاء نظام يلتقط الاستثناءات بمستويات مختلفة من التحديد ويبلغ عن النوع الذي تم التقاطه.

ستقوم بتنظيم الكود الخاص بك عبر ثلاثة ملفات:

  • ExceptionThrower.java: قم بإنشاء فئة (class) يمكنها إطلاق أنواع مختلفة من الاستثناءات بناءً على المدخلات. يجب أن تحتوي الفئة الخاصة بك على ثلاث طرق ثابتة (static methods):

    triggerRuntime(String type) - بناءً على سلسلة النوع (type string)، قم بإطلاق استثناءات وقت تشغيل (runtime exceptions) مختلفة:

    • إذا كان النوع هو "null"، فقم بإطلاق NullPointerException مع الرسالة "Null value encountered"
    • إذا كان النوع هو "index"، فقم بإطلاق ArrayIndexOutOfBoundsException مع الرسالة "Invalid index"
    • إذا كان النوع هو "argument"، فقم بإطلاق IllegalArgumentException مع الرسالة "Bad argument"

    triggerArithmetic() - قم بإطلاق ArithmeticException مع الرسالة "Division error"

    triggerGeneric() - قم بإطلاق RuntimeException مع الرسالة "Generic runtime error"

  • ExceptionAnalyzer.java: قم بإنشاء فئة تلتقط الاستثناءات في مستويات هرمية مختلفة وتحدد ما تم التقاطه. قم بتضمين هذه الطرق الثابتة:

    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() لاسترداد رسالته. يوضح هذا التحدي كيف أن التقاط نوع استثناء أب يلتقط أيضًا جميع أبنائه - وهو مفهوم أساسي عند تحديد مدى دقة معالجة الاستثناءات الخاصة بك!

ورقة مرجعية

تعتمد معالجة الاستثناءات في Java على تسلسل هرمي للفئات يبدأ من Throwable:

Throwable
├── Error          // مشاكل خطيرة (لا تقم بالتقاطها)
└── Exception      // مشاكل يمكن تداركها
    └── RuntimeException  // استثناءات غير مفحوصة

تمثل Error مشاكل خطيرة في JVM مثل OutOfMemoryError أو StackOverflowError والتي لا ينبغي للتطبيقات معالجتها.

تنقسم Exception إلى استثناءات مفحوصة (checked exceptions - فئات فرعية مباشرة) واستثناءات غير مفحوصة (unchecked exceptions - فئات فرعية من RuntimeException):

Exception
├── IOException           // مشاكل في الملفات/الشبكة
├── SQLException          // مشاكل في قاعدة البيانات
└── RuntimeException
    ├── NullPointerException
    ├── ArrayIndexOutOfBoundsException
    └── IllegalArgumentException

التقاط نوع استثناء أب يؤدي أيضاً إلى التقاط جميع أبنائه:

try {
    // some code
} catch (Exception e) {
    // يلتقط جميع الاستثناءات
}

try {
    // some code
} catch (RuntimeException e) {
    // يلتقط فقط استثناءات وقت التشغيل والفئات الفرعية منها
}

استخدم 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: اطبع "=== Specific Catch ===" واستدعِ ExceptionAnalyzer.analyzeSpecific(type)
        
        // TODO: اطبع سطرًا فارغًا، ثم "=== Parent Catch ==="، ثم استدعِ ExceptionAnalyzer.analyzeWithParent()
        
        // TODO: اطبع سطرًا فارغًا، ثم "=== Grandparent Catch ==="، ثم استدعِ ExceptionAnalyzer.analyzeWithGrandparent()
    }
}
quiz iconاختبر نفسك

يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.

جميع دروس Object Oriented Programming