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

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

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

نظام معالجة الاستثناءات في جافا مبني على تسلسل هرمي منظم للفئات جذوره في فئة 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: قم بإنشاء فئة يمكنها إطلاق أنواع مختلفة من الاستثناءات بناءً على المدخلات. يجب أن تحتوي الفئة الخاصة بك على ثلاث طرق ثابتة (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() - قم بإطلاق IllegalStateException مع الرسالة "Generic runtime error" (تسلسله الهرمي هو Exception > RuntimeException > IllegalStateException)

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

جرّب بنفسك

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