תכנות מתקדם ב-Java/חריגות זמן ריצה: הבדלים בין גרסאות בדף

תוכן שנמחק תוכן שנוסף
Johnny Zoo (שיחה | תרומות)
אין תקציר עריכה
Johnny Zoo (שיחה | תרומות)
אין תקציר עריכה
שורה 211:
 
===היררכייה של חריגות===
כאמור, כל החריגות הרגילות (Checked exceptions) יורשות את המחלקה Exception (או מחלקות שיורשות ממנה). שימוש בירושה עם חריגות מאפשר לנו גמישות רבה, ובפרט:
* שיטה יכולה להכריז כי היא זורקת חריגה מסויימת, ובפועל תזרוק חריגה מטיפוס אחר, שיורש את הטיפוס עליו הכריזה.
* בתוך בלוק Try-Catch נתפסות תחילה החריגות שנמצאות נמוך יותר בסולם הירושה, וזה מאפשר לנו לטפל בצורה שונה בחריגות שנמצאות במקומות שונים בעץ הירושה.
נבין זאת טוב יותר באמצעות דוגמה. נניח שכתבנו שרת אינטרנט, ובמהלך הפרוייקט השתמשנו בכמה סוגי חריגות:
 
<source lang = "java">
public class WebServerException extends Exception
</source>
 
<source lang = "java">
public class ProtocolException extends WebServerException
</source>
 
<source lang = "java">
public class ClientException extends WebServerException
</source>
 
הטיפוס הראשון - {{קוד בשורה|WebServerException}} הוא חריגה כללית עבור הפרוייקט. שני הטיפוסים האחרים יורשים את המחלקה {{קוד בשורה|WebServerException}}.
 
נניח שכתבנו את השיטה הבאה:
 
<source lang = "java">
public void doSomething() throws WebServerException {
...
}
</source>
 
השיטה הזו יכולה לזרוק חריגות מטיפוס {{קוד בשורה|WebServerException}}, מטיפוס {{קוד בשורה|ProtocolException}}, או מטיפוס {{קוד בשורה|ClientException}}. בלוק Try-Catch שבתוכו תהייה קריאה לשיטה, לעומת זאת, חייב לתפוס את {{קוד בשורה|WebServerException}} או מחלקה שנמצאת גבוה ממנה בסולם הירושה (במקרה זה - Exception). במידת הצורך, ניתן לתפוס בתוך הבלוק גם חריגות מטיפוס ProtocolException או ClientException. דוגמה לבלוק Try-Catch שקורא לשיטה זו:
<source lang = "java">
try {
doSomething();
} catch(ProtocolException e) {
...
} catch(WebServerException e) {
...
} catch(Exception e) {
...
}
</source>
שימו לב שיש חשיבות לסדר בלוקי ה-Catch. בזמן תפיסת חריגה, הפנייה לבלוקי ה-Catch נעשית על פי הסדר. לכן, כאשר תופסים חריגה שיורשת חריגה אחרת, חייבים לתפוס תחילה את החריגה שנמצאת נמוך יותר בסולם הירושה, אחרת לא יהיה לכך משמעות. למשל, בצורה הבאה:
<source lang = "java">
try {
doSomething();
} catch(WebServerException e) {
...
} catch(ProtocolException e) {
...
}
</source>
אם תיזרק חריגה מטיפוס {{קוד בשורה|ProtocolException}}, היא תיתפס בבלוק הראשון (של WebServerException), מכיוון שהיא מרחיבה אותה. משום כך, הבלוק של {{קוד בשורה|ProtocolException}} כלל לא יהיה נגיש, והתוכנית לא תעבור הידור.
 
אם כך:
* שיטה יכולה לזרוק חריגה מכל טיפוס עליו היא הכריזה או טיפוס שיורש טיפוס עליו היא הכריזה.
* אם שיטה הכריזה על זריקה של חריגה, בבלוק ה-Try-Catch היא חייבת לתפוס חריגה מטיפוס זה או מטיפוס שנמצא גבוה יותר בסולם הירושה.
* ניתן לתפוס בבלוק Try-Catch חריגות שנמצאות במקומות שונים באותו סולם ירושה. במקרה זה, בלוקי ה-Catch עבור המחלקות שנמצאות במקום נמוך יותר בסולם הירושה חייבים להופיע לפני הבלוקים המתאימים עבור החריגות שנמצאות גבוה מהם.
 
===כתיבה של מחלקות חריגות חדשות===