היי! בשיעור האחרון התוודענו לחריגים בשפת ג'אווה, וראינו דוגמאות כיצד לעבוד איתם. היום נסתכל לעומק על מבנה החריגים, ונלמד איך לכתוב את החריגים שלנו :)

סוגי חריגים

כפי שאמרנו קודם, יש הרבה חריגים בג'אווה, כמעט 400! אבל כולם מחולקים לקבוצות, אז די קל לזכור אותם. כך זה נראה: חריגים: מסומנים, לא מסומנים ומותאמים אישית - 2 לכל החריגים יש אב קדמון משותף בכיתה Throwable. שתי קבוצות עיקריות נגזרות ממנו: חריגים ( חריג ) ושגיאות ( שגיאה ). שגיאה - זו מייצגת שגיאת זמן ריצה קריטית הקשורה לפעולת המכונה הוירטואלית של Java. ברוב המקרים, אין צורך לטפל בשגיאה, מכיוון שהיא מעידה על כמה פגמים חמורים בקוד. המפורסמים שבהם הם StackOverflowError (זה מתרחש, למשל, כאשר מתודה קוראת לעצמה בלי סוף) ו- OutOfMemoryError (זה מתרחש כאשר אין מספיק זיכרון ליצירת אובייקטים חדשים). כפי שאתה יכול לראות, במצבים אלה, בדרך כלל אין מה לטפל בזמן הריצה: הקוד פשוט נכתב בצורה שגויה ויש צורך לעבד אותו מחדש. חריגה - זה מייצג, ובכן, חריג: מצב חריג, לא מתוכנן, המתרחש בזמן שהתוכנית פועלת. הם לא רציניים כמו שגיאה, אבל הם עדיין דורשים את תשומת הלב שלנו. כל החריגים מחולקים ל-2 סוגים: מסומנים ולא מסומנים . חריגים: מסומנים, לא מסומנים ומותאמים אישית - 3 כל החריגים המסומנים נגזרים מהכיתה Exception. מה זאת אומרת "בדק"? רמזנו לכך בשיעור האחרון: "מהדר ג'אווה מכיר אפוא את החריגים הנפוצים ביותר ואת המצבים שבהם הם עלולים להתרחש." לדוגמה, הוא יודע שאם הקוד קורא נתונים מקובץ, הקובץ יכול בקלות לא להתקיים. ויש הרבה מצבים כאלה (שזה יכול להסיק). בהתאם לכך, המהדר בודק את הקוד שלנו מראש עבור נוכחותם של חריגים פוטנציאליים אלה. אם הוא ימצא אותם, הוא לא יקמפל את הקוד עד שנטפל בהם או נזרוק אותם מחדש. הסוג השני של חריגים הוא "לא מסומן". הם נגזרים מהכיתה RuntimeException. במה הם שונים מחריגים מסומנים? נראה שיש גם המון מחלקות שונות שנגזרות מהן RuntimeException(המתארות חריגים בזמן ריצה). ההבדל הוא שהמהדר אינו צופה את השגיאות הללו. נראה שזה אומר, "כאשר הקוד נכתב, לא מצאתי שום דבר חשוד, אבל משהו השתבש בזמן שהוא פעל. ככל הנראה, יש שגיאות בקוד!" ואכן זה נכון. חריגים לא מסומנים הם לרוב תוצאה של שגיאות מתכנת. והמהדר כמובן לא יכול לחזות כל מצב רע אפשרי שאנשים עלולים ליצור במו ידיהם. :) לכן, זה לא בודק אם חריגים כאלה מטופלים בקוד שלנו. כבר נתקלת במספר חריגים שלא מסומנים:
  • חריגה אריתמטית מתרחשת כאשר מחלקים באפס
  • ArrayIndexOutOfBoundsException מתרחשת כאשר אתה מנסה לגשת למיקום מחוץ למערך.
כמובן, אתה יכול לדמיין שיוצרי ג'אווה היו יכולים להציג טיפול מחייב בחריגים, אבל במקרה זה הקוד יהיה מסובך מדי. עבור כל פעולת חלוקה, האם תצטרך לכתוב בלוק try-catchכדי לבדוק אם חילק בטעות באפס? בכל פעם שניגשת למערך, תצטרך לכתוב בלוק try-catchכדי לבדוק אם האינדקס שלך מחוץ לתחום. הכל יהיה קוד ספגטי ויהיה בלתי קריא לחלוטין. הגיוני שהרעיון הזה נזנח. כתוצאה מכך, אין צורך לטפל בחריגים שלא מסומנים בבלוקים try-catchאו לזרוק אותם מחדש (אם כי זה אפשרי מבחינה טכנית, כמו עם Error).

איך לזרוק חריג משלך

כמובן, היוצרים של Java לא יכולים לחזות כל מצב חריג שעלול להיווצר בתוכניות. יש יותר מדי תוכניות בעולם, והן מגוונות מדי. אבל זה לא מה לדאוג, כי אתה יכול ליצור חריג משלך, במידת הצורך. זה מאוד קל לעשות. כל מה שאתה צריך לעשות הוא ליצור כיתה משלך. אתה צריך להיות בטוח ששמו מסתיים ב"חריגה". המהדר לא דורש זאת, אבל מתכנתים אחרים הקוראים את הקוד שלך יבינו מיד שמדובר במחלקת חריג. בנוסף, ציינו שהמחלקה עוברת בירושה מהמחלקה Exception(הקומפיילר אכן דורש זאת). לדוגמה, נניח שיש לנו Dogשיעור. אנחנו יכולים לטייל עם הכלב בשיטה walk(). אבל לפני שנעשה זאת, עלינו לבדוק אם חיית המחמד שלנו לובשת צווארון, רצועה ולוע. אם משהו מהציוד הזה חסר, אנו זורקים חריג משלנו: DogIsNotReadyException . הקוד שלו נראה כך:
public class DogIsNotReadyException extends Exception {

   public DogIsNotReadyException(String message) {
       super(message);
   }
}
כדי לציין שהמחלקה היא חריגה, עליך לכתוב " exception exception " אחרי שם המחלקה (משמעות הדבר היא "המחלקה נגזרת ממחלקת החריגה"). בקונסטרוקטור פשוט קוראים Exceptionלבנאי המחלקה עם הודעת String (אם החריג מתרחש, נציג את ההודעה, תיאור השגיאה, למשתמש). כך זה נראה בקוד הכיתה שלנו:
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("We're getting ready for a walk!");
   if (isCollarPutOn && isLeashPutOn && isMuzzlePutOn) {
       System.out.println("Hooray, let's go for a walk! " + name + " is very happy!");
   } else {
       throw new DogIsNotReadyException(name + " is not ready for a walk! Check the gear!");
   }
 }

}
כעת walk()השיטה שלנו זורקת DogIsNotReadyException . זה נעשה עם מילת המפתח זריקה. כפי שאמרנו קודם, חריג הוא אובייקט. לכן, כאשר מתרחש חריג (לכלב חסר משהו) בשיטה שלנו, אנו יוצרים DogIsNotReadyExceptionאובייקט חדש וזורקים אותו באמצעות מילת המפתח throw. אנו מוסיפים " זורק DogIsNotReadyException " להצהרת השיטה. במילים אחרות, כעת המהדר מודע לכך שהקריאה לשיטה walk()עלולה להפוך למצב חריג. בהתאם לכך, יש לטפל בחריג זה אם אנו קוראים לשיטה זו איפשהו בתוכנית שלנו. בואו ננסה לעשות זאת בשיטה main():
public static void main(String[] args) {

   Dog dog = new Dog("Buddy");
   dog.putCollar();
   dog.putMuzzle();
   dog.walk();// Unhandled exception: DogIsNotReadyException
}
זה לא יתבצע קומפילציה. החריג אינו מטופל! אנו עוטפים את הקוד שלנו בבלוק try-catchכדי לטפל בחריג:
public static void main(String[] args) {

   Dog dog = new Dog("Buddy");
   dog.putCollar();
   dog.putMuzzle();
   try {
       dog.walk();
   } catch (DogIsNotReadyException e) {
       System.out.println(e.getMessage());
       System.out.println("Checking the gear! Is the collar on? " + dog.isCollarPutOn + "\r\n Is the leash on? "
       + dog.isLeashPutOn + "\r\n Is the muzzle on? " + dog.isMuzzlePutOn);
   }
}
עכשיו בואו נסתכל על פלט הקונסולה: הקולר על! הלוע דלוק! אנחנו מתכוננים לטיול! באדי לא מוכן לטיול! בדוק את הציוד! בודק את הציוד! הקולר על? נכון הרצועה? false האם הלוע דלוק? נכון תראה כמה יותר אינפורמטיבי פלט הקונסולה היה! אנו רואים כל צעד שנעשה בתוכנית; אנו רואים היכן התרחשה השגיאה, ונוכל גם לראות מיד בדיוק מה הכלב שלנו חסר. :) וככה אתה יוצר חריגים משלך. כפי שאתה יכול לראות, אין בזה שום דבר מסובך. ולמרות שיוצרי ג'אווה לא טרחו לכלול בשפה חריג מיוחד לכלבים מצוידים גרוע, תיקנו את הפיקוח שלהם. :)

קריאה נוספת: