JavaRush /مدونة جافا /Random-AR /الاستثناءات: محددة وغير محددة وخاصة بك

الاستثناءات: محددة وغير محددة وخاصة بك

نشرت في المجموعة
مرحبًا! في المحاضرة الأخيرة، تعرفنا على هذا الجانب من لغة Java كاستثناءات وشاهدنا أمثلة على العمل معها. اليوم سنلقي نظرة أعمق على بنيتها، وسنتعلم أيضًا كيفية كتابة الاستثناءات الخاصة بنا :)

أنواع الاستثناءات

كما قلنا، هناك الكثير من فئات الاستثناء في Java، ما يقرب من 400! لكنها جميعها مقسمة إلى مجموعات، لذلك من السهل تذكرها. إليك ما يبدو عليه الأمر: الاستثناءات: المحددة وغير المحددة والخاصة بك - 2جميع الاستثناءات لها فئة سلف مشتركة Throwable. منه مجموعتان كبيرتان - الاستثناءات (الاستثناء) والأخطاء (الخطأ). الخطأ هو خطأ فادح أثناء تنفيذ البرنامج المرتبط بتشغيل جهاز Java الظاهري. في معظم الحالات، لا يلزم معالجة الخطأ، لأنه يشير إلى بعض العيوب الخطيرة في الكود. الأخطاء الأكثر شهرة: StackOverflowError- تحدث، على سبيل المثال، عندما تستدعي الطريقة نفسها إلى ما لا نهاية، و OutOfMemoryError- تحدث عندما لا تكون هناك ذاكرة كافية لإنشاء كائنات جديدة. كما ترون، في هذه المواقف، في أغلب الأحيان لا يوجد شيء خاص للمعالجة - الكود ببساطة مكتوب بشكل غير صحيح ويحتاج إلى إعادة بنائه. الاستثناءات هي في الواقع استثناءات: حالة استثنائية غير مخطط لها حدثت أثناء تشغيل البرنامج. هذه ليست أخطاء خطيرة مثل الخطأ، ولكنها تتطلب اهتمامنا. تنقسم جميع الاستثناءات إلى نوعين - محددة ( محددة ) وغير محددة ( غير محددة ). الاستثناءات: المحددة وغير المحددة والخاصة بك - 3جميع الاستثناءات المحددة تأتي من Exception. ماذا يعني "يمكن التحقق منه"؟ لقد ذكرنا ذلك جزئيًا في المحاضرة الأخيرة : "...مترجم Java يعرف الاستثناءات الأكثر شيوعًا، ويعرف المواقف التي يمكن أن تحدث فيها." على سبيل المثال، يعرف أنه إذا قرأ المبرمج البيانات من ملف في التعليمات البرمجية، فمن الممكن أن ينشأ الموقف بسهولة بأن الملف غير موجود. وهناك الكثير من هذه المواقف التي يمكنه التنبؤ بها مسبقًا. لذلك، يقوم المترجم بفحص الكود الخاص بنا مسبقًا بحثًا عن الاستثناءات المحتملة. إذا عثر عليها، فلن يقوم بتجميع التعليمات البرمجية حتى نقوم بمعالجتها أو إعادة توجيهها إلى الأعلى. النوع الثاني من الاستثناء هو "غير محدد". يأتون من الصف RuntimeException. وكيف تختلف عن تلك التي يتم اختبارها؟ يبدو أن هناك أيضًا مجموعة من الفئات المختلفة التي تأتي من RuntimeExceptionاستثناءات محددة لوقت التشغيل وتصفها. الفرق هو أن المترجم لا يتوقع هذه الأخطاء. ويبدو أنه يقول: “في وقت كتابة الكود، لم أجد أي شيء مريب، ولكن حدث خطأ ما أثناء عمله. يبدو أن هناك أخطاء في الكود!" وهو بالفعل كذلك. غالبًا ما تكون الاستثناءات التي لم يتم التحقق منها نتيجة لأخطاء المبرمج. ومن الواضح أن المترجم غير قادر على توفير جميع المواقف غير الصحيحة المحتملة التي يمكن للأشخاص إنشاؤها بأيديهم :) لذلك، لن يتحقق من معالجة هذه الاستثناءات في التعليمات البرمجية الخاصة بنا. لقد واجهت بالفعل العديد من الاستثناءات التي لم يتم التحقق منها:
  • ArithmeticExceptionيحدث عند القسمة على صفر
  • ArrayIndexOutOfBoundsExceptionيحدث عند محاولة الوصول إلى خلية خارج المصفوفة.
من الناحية النظرية، بالطبع، كان بإمكان منشئي Java تقديم معالجة إلزامية لمثل هذه الاستثناءات، ولكن ماذا سيصبح الكود بعد ذلك؟ مع أي عملية لقسمة الأعداد، سيتعين عليك كتابة محاولة للتحقق مما إذا كنت تقسم عن طريق الخطأ على صفر؟ عند الوصول إلى مصفوفة، سيتعين عليك كتابة محاولة للتحقق مما إذا كنت قد تجاوزت هذه الحدود. أي رمز مكتوب سيكون معكرونة وغير قابل للقراءة تمامًا. ومن المنطقي أن يتم التخلي عن هذه الفكرة. لذلك، لا يلزم معالجة الاستثناءات غير المحددة في كتل محاولة الالتقاط أو طرحها إلى الأعلى، على الرغم من أن هذا ممكن تقنيًا، كما هو الحال مع الخطأ.

كيفية رمي الاستثناء الخاص بك

بالطبع، لا يستطيع منشئو Java توفير جميع المواقف الاستثنائية التي قد تنشأ في البرامج. هناك الكثير من البرامج في العالم، وهي مختلفة جدًا. لكن لا بأس بذلك، لأنه يمكنك إنشاء الاستثناءات الخاصة بك إذا لزم الأمر. ويتم ذلك بسهولة بالغة. كل ما عليك فعله هو إنشاء صفك الخاص. ويجب أن ينتهي اسمه بكلمة "استثناء". لا يحتاج المترجم إلى هذا، لكن المبرمجين الذين يقرأون التعليمات البرمجية الخاصة بك سوف يفهمون على الفور أن هذه فئة استثناء. بالإضافة إلى ذلك، عليك الإشارة إلى أن الفصل يأتي من الفصل Exception. وهذا ضروري بالفعل للمترجم والتشغيل الصحيح. على سبيل المثال، لدينا فئة Dog - Dog. يمكننا أن نمشي الكلب باستخدام walk(). ولكن قبل ذلك، نحتاج إلى التحقق مما إذا كان حيواننا الأليف يرتدي طوقًا ومقودًا وكمامة. إذا كان أي من هذه العناصر مفقودًا، فسنطرح الاستثناء الخاص بنا DogIsNotReadyException. سيبدو رمزه كما يلي:
public class DogIsNotReadyException extends Exception {

   public DogIsNotReadyException(String message) {
       super(message);
   }
}
للإشارة إلى أن الفئة هي استثناء، تحتاج إلى كتابة Extend Exception بعد اسم الفئة: وهذا يعني أن "الفئة مشتقة من الفئة استثناء". في المُنشئ، سنقوم ببساطة باستدعاء مُنشئ الفئة Exceptionبخط message- سيعرض للمستخدم رسالة من النظام تصف الخطأ الذي حدث. هذا ما سيبدو عليه في رمز الفصل الخاص بنا:
public class Dog {

   String name;
   boolean isCollarPutOn;
   boolean isLeashPutOn;
   boolean isMuzzlePutOn;

   public Dog(String name) {
       this.name = name;
   }

   public static void main(String[] args) {

   }

   public void putCollar() {

       System.out.println("The collar is on!");
       this.isCollarPutOn = true;
   }

   public void putLeash() {

       System.out.println("The leash is on!");
       this.isLeashPutOn = true;
   }

   public void putMuzzle() {
       System.out.println("The muzzle is on!");
       this.isMuzzlePutOn = true;
   }

   public void walk() throws DogIsNotReadyException {

   System.out.println("Let's go for a walk!");
   if (isCollarPutOn && isLeashPutOn && isMuzzlePutOn) {
       System.out.println("Hurrah, let's go for a walk!" + name + " I am glad!");
   } else {
       throw new DogIsNotReadyException("Dog " + name + "not ready for a walk! Check your gear!");
   }
 }

}
الآن طريقتنا walk()تطرح استثناءً DogIsNotReadyException. يتم ذلك باستخدام الكلمة الأساسية throw. كما قلنا سابقًا، الاستثناء هو كائن. لذلك، في طريقتنا، عندما يحدث موقف استثنائي - شيء مفقود لدى الكلب - نقوم بإنشاء كائن فئة جديد DogIsNotReadyExceptionوإدخاله في البرنامج باستخدام الكلمة throw. walk()نضيف رميات إلى توقيع الطريقة DogIsNotReadyException. بمعنى آخر، أصبح المترجم الآن على علم بأن استدعاء الأسلوب walk()قد يؤدي إلى حدوث استثناء. لذلك عندما نستدعي هذا في مكان ما في البرنامج، يجب معالجة الاستثناء. دعونا نحاول القيام بذلك بالطريقة main():
public static void main(String[] args) {

   Dog dog = new Dog("Mukhtar");
   dog.putCollar();
   dog.putMuzzle();
   dog.walk();//Unhandled exception: DogIsNotReadyException
}
لا يتم تجميعها، ولم تتم معالجة الاستثناء! دعونا نلف الكود الخاص بنا في كتلة try-catchللتعامل مع الاستثناء:
public static void main(String[] args) {

   Dog dog = new Dog("Mukhtar");
   dog.putCollar();
   dog.putMuzzle();
   try {
       dog.walk();
   } catch (DogIsNotReadyException e) {
       System.out.println(e.getMessage());
       System.out.println("Checking equipment! Is the collar on?" + dog.isCollarPutOn + "\r\n Is the leash on?"
       + dog.isLeashPutOn + "\r\n Are you wearing a muzzle?" + dog.isMuzzlePutOn);
   }
}
الآن دعونا نلقي نظرة على إخراج وحدة التحكم:

Ошейник надет! 
Намордник надет! 
Собираемся на прогулку! 
Собака Мухтар не готова к прогулке! Проверьте экипировку! 
Проверяем снаряжение! Ошейник надет? true
Поводок надет? false 
Намордник надет? true
انظر إلى أي مدى أصبحت مخرجات وحدة التحكم أكثر إفادة! نرى كل خطوة حدثت في البرنامج؛ نرى مكان حدوث الخطأ ونلاحظ على الفور ما يفتقده كلبنا بالضبط :) هذه هي الطريقة التي ننشئ بها الاستثناءات الخاصة بنا. كما ترون، لا شيء معقد. وعلى الرغم من أن مطوري Java لم يكلفوا أنفسهم عناء إضافة استثناء خاص إلى لغتهم للكلاب المجهزة بشكل غير صحيح، فقد قمنا بتصحيح إشرافهم :)
تعليقات
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION