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

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

جزء من قسم البرمجة كائنية التوجه في رحلة 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
}

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

challenge icon

التحدي

سهل

لنَبْنِ محللًا للاستثناءات يوضّح كيفية عمل التسلسل الهرمي للاستثناءات في 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)

  • 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()
    }
}
quiz iconاختبر نفسك

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

جميع دروس البرمجة كائنية التوجه

تدرّب بنفسك: مترجم Java عبر الإنترنت