Logo

معمل الاستثناءات وتصحيح الأخطاء في جافا

9 دقائق قراءة
شرائح الدرس
1 / 14

معمل استثناءات جافا والتنقيح

أنواع الأخطاء، تقنية التنقيح، ومعالجة الاستثناءات برشاقة

مقدمة

مرحبًا بك في معمل استثناءات جافا وتصحيح الأخطاء! في هذا المعمل، ستتعلم كيفية:

  • فهم الأنواع المختلفة من الأخطاء في جافا
  • تصحيح أخطاء الكود الخاص بك باستخدام تقنيات بسيطة
  • معالجة الاستثناءات (Exceptions) لمنع تعطّل البرنامج
  • استخدام كتل try-catch بفعالية

الجزء 1: فهم الأخطاء

ما هي الأخطاء؟

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

graph TD
    A[Java Errors] --> B[Compile-Time Errors]
    A --> C[Runtime Errors]
    A --> D[Logical Errors]
    B --> E[Detected before running<br/>Program won't compile]
    C --> F[Occur while running<br/>Program crashes]
    D --> G[Program runs but gives<br/>wrong results]

أنواع الأخطاء

نوع الخطأمتى يحدثمثال
وقت الترجمة (Compile-Time)قبل تشغيل البرنامجفاصلة منقوطة مفقودة، متغير غير مُعرَّف
وقت التشغيل (Runtime)أثناء تشغيل البرنامجالقسمة على صفر، فهرس مصفوفة خارج النطاق
الخطأ المنطقي (Logical)يعمل البرنامج لكن النتيجة خاطئةاستخدام x - y بدلاً من x + y

الجزء 2: الأخطاء الشائعة

أخطاء وقت الترجمة (Compile-Time Errors)

تمنع هذه الأخطاء الكود الخاص بك من الترجمة (Compiling).

1. فاصلة منقوطة مفقودة

int x = 5  // Error: ';' expected

الحل: أضف فاصلة منقوطة في النهاية

int x = 5;

2. متغير غير مُعرَّف

System.out.println(myVar);  // Error: cannot find symbol

الحل: عرّف المتغير أولاً

int myVar = 50;
System.out.println(myVar);

3. عدم تطابق النوع (Type Mismatch)

int x = "Hello";  // Error: incompatible types

الحل: استخدم النوع الصحيح

String x = "Hello";

أخطاء وقت التشغيل (Runtime Errors)

تحدث هذه الأخطاء أثناء تشغيل البرنامج.

1. القسمة على صفر

int x = 10;
int y = 0;
int result = x / y;  // ArithmeticException

المخرج:

Exception in thread "main" java.lang.ArithmeticException: / by zero

2. فهرس مصفوفة خارج النطاق

int[] numbers = {1, 2, 3};
System.out.println(numbers[10]);  // ArrayIndexOutOfBoundsException

المخرج:

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 10

الأخطاء المنطقية (Logical Errors)

هذه الأخطاء هي الأصعب في الاكتشاف لأن البرنامج يعمل دون أن يتعطّل.

int x = 10;
int y = 2;
int result = x - y;  // You meant x + y
System.out.println(result);  // Prints 8 instead of 12

الجزء 3: أساسيات تصحيح الأخطاء (Debugging)

ما هو تصحيح الأخطاء؟

تصحيح الأخطاء (Debugging) هو اكتشاف وإصلاح الأخطاء في الكود الخاص بك.

flowchart LR
    A[Code has bug] --> B[Add print statements]
    B --> C[Run program]
    C --> D[Check output]
    D --> E{Found problem?}
    E -->|No| B
    E -->|Yes| F[Fix bug]
    F --> G[Test again]

استخدام جُمل الطباعة

أبسط طريقة لتصحيح الأخطاء هي استخدام System.out.println().

int x = 10;
int y = 0;
 
System.out.println("Before division");  // This prints
System.out.println("x = " + x);         // This prints
System.out.println("y = " + y);         // This prints
 
int result = x / y;  // Program crashes here
 
System.out.println("Result: " + result);  // Never runs

المخرج:

Before division
x = 10
y = 0
Exception in thread "main" java.lang.ArithmeticException: / by zero

قائمة تحقق تصحيح الأخطاء

✅ اقرأ رسالة الخطأ كاملة
✅ تحقّق من أن جميع المتغيرات مُهيَّأة (Initialized)
✅ اطبع قيم المتغيرات لتتبّع المشكلة
✅ انتبه لأخطاء الانحراف بواحد (Off-by-one) في الحلقات
✅ اختبر بمدخلات مختلفة


الجزء 4: معالجة الاستثناءات (Exception Handling)

ما هي الاستثناءات؟

عند حدوث خطأ، ترمي جافا استثناءً (Exception) (كائن خطأ). دون معالجته، يتعطّل برنامجك.

كتلة try-catch

استخدم try-catch لمعالجة الاستثناءات بسلاسة.

flowchart TD
    A[Start] --> B[Execute try block]
    B --> C{Error occurs?}
    C -->|No| D[Skip catch block]
    C -->|Yes| E[Execute catch block]
    D --> F[Continue program]
    E --> F

الصيغة العامة:

try {
    // Code that might cause an error
} catch (Exception e) {
    // Code to handle the error
}

مثال: معالجة خطأ فهرس المصفوفة

بدون try-catch (يتعطّل البرنامج):

public class Main {
    public static void main(String[] args) {
        int[] myNumbers = {1, 2, 3};
        System.out.println(myNumbers[10]);  // Crash!
    }
}

المخرج:

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 10

باستخدام try-catch (يستمر البرنامج):

public class Main {
    public static void main(String[] args) {
        try {
            int[] myNumbers = {1, 2, 3};
            System.out.println(myNumbers[10]);
        } catch (Exception e) {
            System.out.println("Something went wrong.");
        }
    }
}

المخرج:

Something went wrong.

الجزء 5: كتلة finally

تُشغَّل كتلة finally دائمًا، سواء حدث خطأ أم لا.

try {
    int[] myNumbers = {1, 2, 3};
    System.out.println(myNumbers[10]);
} catch (Exception e) {
    System.out.println("Something went wrong.");
} finally {
    System.out.println("The 'try catch' is finished.");
}

المخرج:

Something went wrong.
The 'try catch' is finished.
flowchart TD
    A[try block] --> B{Error?}
    B -->|Yes| C[catch block]
    B -->|No| D[Skip catch]
    C --> E[finally block]
    D --> E
    E --> F[Continue]

الجزء 6: الكلمة المفتاحية throw

يمكنك إنشاء استثناءاتك الخاصة باستخدام throw.

مثال: التحقق من العمر

public class Main {
    static void checkAge(int age) {
        if (age < 18) {
            throw new ArithmeticException("Access denied - You must be at least 18 years old.");
        } else {
            System.out.println("Access granted - You are old enough!");
        }
    }
 
    public static void main(String[] args) {
        checkAge(15);  // Will throw exception
    }
}

المخرج:

Exception in thread "main" java.lang.ArithmeticException: Access denied - You must be at least 18 years old.

استخدام throw مع try-catch

public class Main {
    static void checkAge(int age) {
        if (age < 18) {
            throw new ArithmeticException("Access denied - You must be at least 18 years old.");
        } else {
            System.out.println("Access granted - You are old enough!");
        }
    }
 
    public static void main(String[] args) {
        try {
            checkAge(15);
        } catch (Exception e) {
            System.out.println("Error: " + e.getMessage());
        }
    }
}

المخرج:

Error: Access denied - You must be at least 18 years old.

الجزء 7: Try-with-Resources

مشكلة الإدارة اليدوية للموارد

عند العمل مع الملفات أو التدفقات (Streams)، تحتاج إلى إغلاقها يدويًا:

import java.io.FileOutputStream;
 
public class Main {
    public static void main(String[] args) {
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream("output.txt");
            fos.write("Hello".getBytes());
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (fos != null) fos.close();  // Manual closing
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

الحل: try-with-resources

قدّمت جافا 7 صيغة try-with-resources لإغلاق الموارد تلقائيًا.

الصيغة العامة:

try (ResourceType resource = new ResourceType()) {
    // Use the resource
}
// Resource is automatically closed here

مثال:

import java.io.FileOutputStream;
 
public class Main {
    public static void main(String[] args) {
        try (FileOutputStream fos = new FileOutputStream("output.txt")) {
            fos.write("Hello".getBytes());
        } catch (Exception e) {
            e.printStackTrace();
        }
        // No need to close fos - Java does it automatically!
    }
}

موارد متعددة

يمكنك إدارة عدة موارد في وقت واحد:

import java.io.FileWriter;
import java.io.BufferedWriter;
 
public class Main {
    public static void main(String[] args) {
        try (FileWriter fw = new FileWriter("output.txt");
             BufferedWriter bw = new BufferedWriter(fw)) {
            bw.write("Hello World!");
        } catch (Exception e) {
            e.printStackTrace();
        }
        // Both resources are automatically closed in reverse order
    }
}
flowchart LR
    A[Open Resource 1] --> B[Open Resource 2]
    B --> C[Use Resources]
    C --> D[Close Resource 2]
    D --> E[Close Resource 1]

الفوائد:

  • ✅ كود أنظف - لا حاجة لاستدعاءات close() يدوية
  • ✅ أكثر أمانًا - تُغلَق الموارد حتى في حال حدوث استثناء
  • ✅ تلقائي - تتولّى جافا الإغلاق نيابة عنك

قاعدة عامة: عند العمل مع الملفات، أو التدفقات، أو اتصالات قواعد البيانات، استخدم دائمًا try-with-resources!


تمارين المعمل

التمرين 1: إصلاح أخطاء وقت الترجمة

اعثر على الأخطاء في هذا الكود وأصلحها:

public class Main {
    public static void main(String[] args) {
        int age = 25
        String name
        System.out.println("Name: " + name);
        System.out.println("Age: " + age);
    }
}

التمرين 2: معالجة أخطاء وقت التشغيل

عدّل هذا الكود لمعالجة خطأ القسمة على صفر:

public class Main {
    public static void main(String[] args) {
        int[] numbers = {10, 20, 30};
        int divisor = 0;
        
        int result = numbers[0] / divisor;
        System.out.println("Result: " + result);
    }
}

التمرين 3: إنشاء استثناء مخصّص

اكتب برنامجًا:

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

التمرين 4: استخدام try-with-resources

اكتب برنامجًا:

  1. ينشئ ملفًا باسم "student.txt"
  2. يكتب اسمك ورقمك الجامعي في الملف
  3. يستخدم try-with-resources لضمان إغلاق الملف بشكل صحيح

أنواع الاستثناءات الشائعة

الاستثناءالسبب
ArithmeticExceptionالقسمة على صفر
ArrayIndexOutOfBoundsExceptionفهرس مصفوفة غير صالح
NullPointerExceptionاستخدام كائن فارغ (null)
FileNotFoundExceptionالملف غير موجود
NumberFormatExceptionتحويل غير صالح من نص إلى رقم

الملخّص

mindmap
  root((Java Exceptions<br/>& Debugging))
    Error Types
      Compile-Time
      Runtime
      Logical
    Debugging
      Print Statements
      IDE Debugger
      Check Variables
    Exception Handling
      try-catch
      finally
      throw
    Best Practices
      try-with-resources
      Specific Exceptions
      Meaningful Messages

أهم النقاط

  1. الأخطاء تحدث - حتى للمبرمجين ذوي الخبرة
  2. صحّح الأخطاء بشكل منهجي - استخدم جُمل الطباعة والمصحِّحات (Debuggers)
  3. عالِج الاستثناءات - استخدم try-catch لمنع تعطّل البرنامج
  4. أغلق الموارد - استخدم try-with-resources للملفات والتدفقات
  5. اختبر بشكل شامل - جرّب مدخلات مختلفة لاكتشاف الأخطاء

الخطوات التالية

  • تدرّب على كتابة كتل try-catch لسيناريوهات مختلفة
  • تعلّم عن أنواع الاستثناءات المحدَّدة
  • استكشف أدوات تصحيح الأخطاء في بيئات التطوير (IntelliJ IDEA، Eclipse، NetBeans)
  • ادرس تراتبية (Hierarchy) الاستثناءات في جافا

مصادر إضافية

  • توثيق استثناءات جافا: https://docs.oracle.com/javase/tutorial/essential/exceptions/
  • تدرّب على تقنيات تصحيح الأخطاء باستخدام بيئة التطوير الخاصة بك
  • راجع رسائل الخطأ - غالبًا ما تخبرك بالضبط بمكان الخلل!

حظًا موفقًا في تمارين المعمل! تذكّر: كلما صحّحت الأخطاء أكثر، أصبحت أفضل في اكتشاف المشكلات وإصلاحها بسرعة.