English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

تعليمات Java الأساسية

Java التحكم في العملية

Java Arrays

Java توجيه الأحداث (I)

Java توجيه الأحداث (II)

Java توجيه الأحداث (III)

معالجة الاستثناءات Java

Java List

Java Queue (الصف)

Java Map Collections

Java Set Collections

Java إدخال/إخراج (I/O)

Java Reader/Writer

موضوعات أخرى Java

معالجة الاستثناءات Java

في هذا الدرس، ستعلم كيفية معالجة الاستثناءات باستخدام Java. من أجل معالجة الاستثناءات، سنستخدم block try...catch...finally.

في الدرس السابق، تعرفنا على الاستثناءات. الاستثناء هو حدث غير متوقع يحدث أثناء تنفيذ البرنامج.

التقاطع ومعالجة الاستثناءات

في Java، نستخدم مكونات معالجة الاستثناءات try، catch و block finally لمعالجة الاستثناءات.

للقبض على معالجة الاستثناءات، سنقوم بوضع block try...catch...finally حول رمز قد يولد استثناءً. block finally هو اختياري.

القواعد النحوية لـ try...catch...finally هي:

try {
  // رمز
} catch (ExceptionType e) { 
  //block capture
}
  //block finally
}

block try ... catch Java

يوضع رمز قد يولد استثناءً داخل block try.

بعد كل block try يجب أن يتبعه block catch أو finally. عند حدوث استثناء، سيتم القبض عليه من قبل block الذي يتبعه.

 لا يمكن استخدام block catch بشكل مستقل، يجب أن يتبعه block try.

مثال 1: try ... catch

class Main {
  public static void main(String[] args) {
    try {
      int divideByZero = 5 / 0;
      System.out.println("الكود المتبقي في حزمة try");
    }
      System.out.println("ArithmeticException => " + e.getMessage());
    }
  }
}

نتائج الإخراج

ArithmeticException => / by zero

في هذا المثال

  • نحن نقسم الرقم إلى صفر في حزمة try. هذا ينتج استثناء ArithmeticException.

  • عندما يحدث استثناء، يقوم البرنامج بتخطي باقي الكود في حزمة try.

  • في هذا المكان، قمنا بإنشاء حزمة catch لمعالجة استثناء ArithmeticException. لذلك، يتم تنفيذ الجمل في حزمة catch.

إذا لم يكن أي جملة في حزمة try قد أحدثت استثناءً فسيتم السكوت عن كود الحزمة من catch.

عدة حزم استثناء

للمجلس الأولي يمكن أن يكون هناك حزمة واحدة أو أكثر من catch.

نوع المعامل في كل حزمة catch يشير إلى نوع الاستثناء الذي يمكن معالجته. تسمح الحزم المتعددة بمعالجة كل استثناء بطريقة مختلفة.

مثال 2: عدة حزم استثناء

class ListOfNumbers {
  public int[] arrayOfNumbers = new int[10];
  public void writeList() {
    try {
      arrayOfNumbers[10] = 11;
    }
      System.out.println("NumberFormatException => " + e1.getMessage());
    }
      System.out.println("IndexOutOfBoundsException => " + e2.getMessage());
    }
  }
}
class Main {
  public static void main(String[] args) {
    ListOfNumbers list = new ListOfNumbers();
    list.writeList();
  }
}

نتائج الإخراج

IndexOutOfBoundsException => البدالة 10 خارج الحدود بالنسبة للطول 10

في هذا المثال، نحن نعلن عن مصفوفة صغيرة الحجم من النوع int تسمى arrayOfNumbers.

نحن نعرف أن عدد البدائل يبدأ دائمًا من 0. لذلك، عندما نحاول تخصيص قيمة للبدالة 10، يحدث استثناء IndexOutOfBoundsException لأن نطاق عدد البدائل هو من 0 إلى 9.

عندما يحدث استثناء في حزمة try

  • الاستثناء يتم رميها إلى الحزمة الأولى من catch. الحزمة الأولى من catch لا تعالج استثناء IndexOutOfBoundsException، لذلك يتم تمريرها إلى الحزمة التالية من catch.

  • حزمة catch الثانية في المثال أعلاه هي معالجة استثناء مناسبة لأنها تتعامل مع استثناء IndexOutOfBoundsException. لذلك، تم تنفيذها.

حزمة Finally في Java

للمجلس الأولي فقط يمكن أن يكون هناك حزمة واحدة من try.

جملة finally اختيارية. ولكن إذا تم تعريفها، فإنها ستُنفذ دائمًا (حتى لو لم يحدث استثناء).

إذا حدث استثناء، يتم تنفيذها بعد جملة try...catch. وإذا لم يحدث استثناء، يتم تنفيذها بعد جملة try.

النحو الأساسي للجملة finally هو:

try {
  //code
} 
  //جملة catch
}
 //جملة catch
}
  //جملة finally تستمر في التنفيذ
}

مثال 3: مثال على جملة finally

class Main {
  public static void main(String[] args) {
    try {
      int divideByZero = 5 / 0;
    }
      System.out.println("ArithmeticException => " + e.getMessage());
    }
      System.out.println("جملة finally دائمًا ما تنفذ");
    }
  }
}

نتائج الإخراج

ArithmeticException => / by zero
جملة finally دائمًا ما تنفذ

في هذا المثال، سنقوم بتقسيم الرقم على الصفر. مما يؤدي إلى إطلاق استثناء ArithmeticException يتم القبض عليه في جملة catch، وستنفذ جملة finally دائمًا

استخدام جملة finally يُعتبر ممارسة جيدة. لأنها تحتوي على كود تنظيف مهم، مثل

  • قد يتم تجاوز الكود المكتوب باستخدام جملة return أو continue أو break بشكل غير متوقع

  • إغلاق الملف أو الاتصال

لقد ذكرنا أن finally دائمًا ما تنفذ، وعادة ما يكون مثل هذا. ولكن، في بعض الحالات، لا تنفذ جملة finally:

  • استخدام طريقة System.exit()

  • حدث استثناء في جملة finally

  • السطر يُتوقف

مثال 4: مثال على try, catch و finally

لنأخذ مثالاً، نحاول استخدام FileWriter لإنشاء ملف جديد ونكتب البيانات باستخدام PrintWriter.

import java.io.*;
class ListOfNumbers {
  private int[] list = new int[10];
  public ListOfNumbers() {
    //في مصفوفة القائمة تُخزن القيم الصحيحة
    for (int i = 0; i < 10; i++) {
      list[i] = i;
    } 	
  }
}
  public void writeList() {
    PrintWriter out = null;
    try {
      System.out.println("دخول جملة try");
      //إنشاء ملف جديد OutputFile.txt
      out = new PrintWriter(new FileWriter("OutputFile.txt"));
      //كتابة القيم من مصفوفة القائمة إلى ملف جديد تم إنشاؤه
      for (int i = 0; i < 10; i++) {
        out.println("قيمة في: " + i + " = " + list[i]);
      }
    }
      System.out.println("IndexOutOfBoundsException => " + e1.getMessage());
    }
      System.out.println("IOException => " + e2.getMessage());
    }
      //تحقق من أن PrintWriter مفتوح
      if (out != null) {
        System.out.println("إغلاق PrintWriter");
        out.close();
      } else {
        System.out.println("لا يمكن فتح PrintWriter");
      }
    }
  }
}
class Main {
  public static void main(String[] args) {
    ListOfNumbers list = new ListOfNumbers();
    list.writeList();
  }
}

عند تشغيل هذا البرنامج، قد تحدث إحدى الاثنتين:

  1. حدث استثناء في جملة try

  2. تنفيذ جملة try بشكل طبيعي

قد يحدث استثناء عند إنشاء FileWriter جديد. إذا لم يتم إنشاء أو كتابة الملف المحدد، فإنه يتم رمي IOException.

عندما يحدث استثناء، سنحصل على الناتج التالي.

دخول جملة try
IOException => OutputFile.txt
لا يمكن فتح PrintWriter

عندما لا يحدث استثناء وينجح تنفيذ جملة try بشكل طبيعي، سنحصل على الناتج التالي.

دخول جملة try
إغلاق PrintWriter

سيتم إنشاء ملف OutputFile.txt، ويشمل ما يلي

قيمة في: 0 = 0
قيمة في: 1 = 1
قيمة في: 2 = 2
قيمة في: 3 = 3
قيمة في: 4 = 4
القيمة في الموضع: 5 = 5
القيمة في الموضع: 6 = 6
القيمة في الموضع: 7 = 7
القيمة في الموضع: 8 = 8
القيمة في الموضع: 9 = 9

عملية try ... catch ... finally

دعونا نحاول أن نفهم بشكل أفضل عملية معالجة الاستثناءات باستخدام المساعدة في المثال السابق.

توضح الصورة أعلاه مسار تنفيذ البرنامج عند حدوث استثناء أثناء إنشاء FileWriter.

  • لإيجاد الطريقة التي حدث فيها الاستثناء، يدعو النظام إلى طريقة writeList()، والتي تدعو بدورها إلى طريقة FileWriter() لإنشاء ملف OutputFile.txt جديد.

  • عند حدوث استثناء، يخطئ النظام في التغاضي عن باقي الكود في قالب try.

  • يبدأ النظام في البحث بالعكس في قائمة التسمية للعثور على معالج استثناء مناسب.

  • في هذا المكان، لا يوجد معالج استثناء لFileWriter، لذا سينفذ النظام بشكل تلقائي إلى الطريقة التالية في قائمة التسمية، وهي writeList.

  • يحتوي طريقة writeList على معالجين استثناء: معالج لIndexOutOfBoundsException، ومعالج آخر لIOException.

  • ثم، سيتعامل النظام بشكل متتابع مع هذه المعالجات.

  • في هذا المثال، المعالج الأول يتعامل مع IndexOutOfBoundsException. هذا لا يتطابق مع IOException التي أُثيرت في قالب try.

  • لذلك، سيتم التحقق مما إذا كان التالي هو معالج IOException. إذا كان نوع الاستثناء المطلق مطابقاً، سيتم تنفيذ الكود في قالب catch المماثل.

  • بعد تنفيذ معالج الاستثناءات، سيتم تنفيذ قالب finally.

  • في هذا السيناريو، لأن حدث استثناء في FileWriter، لم يتم فتح كائن PrintWriter object out، لذا لا يتطلب الإغلاق.

الآن، لنفترض أن لم يحدث أي استثناء أثناء تشغيل هذا البرنامج، وأن قالب try تم تنفيذه بشكل صحيح. في هذه الحالة، سيتم إنشاء ملف OutputFile.txt وسيتم كتابته.

من المعروف أن تنفيذ قالب finally لا يتعلق بمعالجة الاستثناءات. لأن لم يكن هناك استثناء، تم فتح PrintWriter ويتعين إغلاقه. يتم ذلك عن طريق جملة out.close() في قالب finally.

التقاط عدة استثناءات

من بداية Java SE 7 وما فوق، يمكننا الآن استخدام قالب catch واحد لالتقاط أكثر من نوع استثناء.

بهذا يمكن تقليل تكرار الكود وزيادة بسيطته وإنتاجيته.

يمكن استخدام رمز الثلاثي الفاصلة (|) لفصل كل نوع استثناء يمكن معالجته من قبل قالب catch.

جملة try-with-resources هي جملة try تحتوي على إعلان مصادر واحدة أو أكثر.

try {
  // code
catch (ExceptionType1 | Exceptiontype2 ex) { 
  // قالب catch
}

للحصول على معلومات إضافية، يرجى زيارةJava تحديد استثناءات متعددة.

جملة try-with-resources

جملة try-with-resources هي جملة try تحتوي على إعلان مصادر واحدة أو أكثر.

جملة try-with-resources هي جملة try تحتوي على إعلان مصادر واحدة أو أكثر.

try (تعريف المصدر) {
  // استعمال المصدر
catch (ExceptionType e1) {
  // قالب catch
}

الموارد هي الأشياء التي يجب إغلاقها عند انتهاء البرنامج. يجب إعلانها وتحديدها داخل جملة try.

دعونا نأخذ مثالاً.

try (PrintWriter out = new PrintWriter(new FileWriter("OutputFile.txt"))) {
  // استعمال المصدر
}

جملة try-with-resources تُسمى أيضًاإدارة الموارد التلقائية. يتم إغلاق جميع الموارد تلقائيًا في نهاية الجملة.

للحصول على معلومات إضافية، يرجى زيارةجملة try-with-resources Java.