JavaRush /בלוג Java /Random-HE /חריגים: מסומנים, לא מסומנים ושלכם

חריגים: מסומנים, לא מסומנים ושלכם

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

סוגי חריגים

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

איך לזרוק את החריגה שלך

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

   public DogIsNotReadyException(String message) {
       super(message);
   }
}
כדי לציין שמחלקה היא חריגה, עליך לכתוב exception extensions אחרי שם המחלקה: פירוש הדבר הוא ש"המחלקה נובעת מהמחלקה 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