Menu

try-catch ב-Java: טיפול בחריגות בלי שהתוכנית תקרוס

איך משתמשים ב-try-catch ב-Java כדי לטפל בחריגות: תפיסת טיפוסים ספציפיים, בלוק finally, try-with-resources והטעויות שמסתירות באגים.

בדף הזה יש עורכים שאפשר להריץ - לערוך, להריץ ולראות את הפלט מיד.

לתפוס חריגה במקום לקרוס

אתם כבר יודעים שכשמשהו משתבש, Java זורקת חריגה, וחריגה שאף אחד לא מטפל בה עוצרת את התוכנית עם stack trace. בלוק try-catch הוא הדרך לקחת שליטה: עוטפים את הקוד המסוכן ב-try, ואם הוא זורק חריגה, Java קופצת לבלוק ה-catch המתאים במקום לקרוס.

ברגע ש-10 / 0 זורק חריגה, שאר בלוק ה-try מדולג והשליטה עוברת ל-catch. אחרי שה-catch מסתיים, הביצוע ממשיך כרגיל: התוכנית לא מתה.

משתנה ה-catch מחזיק את החריגה

ה-e ב-catch (ArithmeticException e) הוא אובייקט אמיתי. הוא נושא מידע על מה שהשתבש, והחלק השימושי ביותר הוא הודעה:

e.getMessage() מחזירה תיאור קצר. בזמן דיבאג, e.printStackTrace() מדפיסה את כל ה-trace ומראה בדיוק מאיפה החריגה הגיעה. השתמשו בה כשהודעה לבדה לא מספיקה כדי למצוא את הסיבה.

תפסו את הטיפוס הספציפי, לא הכל

בלוק catch תופס רק חריגות שמתאימות לטיפוס שהוצהר בו (או למחלקת משנה שלו). טעות המתחילים הגדולה ביותר היא לתפוס Exception כדי ש"הבעיה תיעלם":

// אל תעשו את זה: זה מסתיר באגים אמיתיים
try {
    doWork();
} catch (Exception e) {
    // בולע NullPointerException, שגיאות הקלדה, שגיאות לוגיקה... הכל
}

תפסו את הטיפוס הצר ביותר שאתם באמת יודעים לטפל בו. אם אתם מצפים לקלט מספרי שגוי, תפסו NumberFormatException. כל מה שלא צפיתם צריך להתפשט הלאה, כדי שבאמת תגלו אותו במקום להמשיך בשקט במצב שבור.

טיפול בכמה טיפוסי חריגות

אפשר לערום כמה בלוקי catch. Java בודקת אותם מלמעלה למטה ומריצה את הראשון שמתאים, לכן סדרו אותם מהספציפי ביותר לכללי ביותר:

כששני טיפוסים מטופלים באותה דרך, השתמשו ב-multi-catch יחיד עם | במקום לשכפל את הבלוק:

מלכודת: טיפוס כללי יותר חייב לבוא אחרי הספציפיים. אם שמים catch (Exception e) ראשון, הבלוקים הספציפיים שאחריו הופכים לבלתי ניתנים להשגה, והקומפיילר דוחה את הקוד.

finally תמיד רץ

בלוק finally רץ אחרי ה-try ואחרי כל catch, לא משנה מה קרה: הצלחה, חריגה שנתפסה ואפילו return מוקדם. זה המקום לניקוי שחייב לקרות תמיד.

"Closing resource" מודפס בין אם החריגה נזרקת ובין אם לא. עם זאת, הימנעו מ-return מתוך finally: הוא עלול להעלים חריגה בשקט או לדרוס ערך שהוחזר מבלוק ה-try.

try-with-resources סוגר דברים בשבילכם

כשעובדים עם משהו שחייב להיסגר, כמו קובץ, חיבור רשת או פקודת מסד נתונים, הצהרה עליו בתוך try (...) סוגרת אותו אוטומטית כשהבלוק מסתיים, גם אם נזרקת חריגה. זה עובד עם כל טיפוס שמממש את ה-interface AutoCloseable.

זה מחליף את הדפוס הישן של פתיחה ב-try וסגירה ב-finally, והוא פחות מועד לטעויות כי אי אפשר לשכוח לסגור. העדיפו אותו בכל פעם שאתם עובדים עם משאב שאפשר לסגור.

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

try-catch נועד למצבים חריגים, לא לתנאים רגילים. תפיסת חריגה יקרה יותר מבדיקה פשוטה, והיא מקשה על קריאת הקוד. אם אפשר לבדוק את התנאי קודם עם בדיקת if-else, עשו את זה:

// הימנעו: שימוש ב-catch כדי לבדוק אם מפתח חסר
try {
    process(map.get(key).trim());
} catch (NullPointerException e) {
    // טיפול במפתח החסר
}

// עדיף: לבדוק במפורש
String value = map.get(key);
if (value != null) {
    process(value.trim());
}

שמרו את catch לדברים שבאמת לא בשליטתכם: קלט שגוי ממשתמש, קבצים חסרים, תקלות רשת.

הבא בתור: NullPointerException

החריגה הנפוצה ביותר שתתפסו (ותגרמו) ב-Java היא NullPointerException: היא מופיעה ברגע שקוראים למתודה על משהו שהתברר שהוא null. בעמוד הבא נצלול בדיוק למה שגורם לה, איך קוראים את ה-stack trace שלה, ואילו הרגלים מונעים ממנה לקרות מלכתחילה.

שאלות נפוצות

איך משתמשים ב-try-catch ב-Java?

שמים את הקוד שעלול לזרוק חריגה בתוך בלוק try, ואחריו מוסיפים בלוק catch שמציין את טיפוס החריגה שרוצים לטפל בה: try { risky(); } catch (IOException e) { ... }. אם הקוד ב-try זורק חריגה מתאימה, Java קופצת ישר לבלוק ה-catch במקום לקרוס. המשתנה (e) מחזיק את אובייקט החריגה, כך שאפשר לקרוא את ההודעה שלה עם e.getMessage().

בשביל מה בלוק finally ב-Java?

בלוק finally רץ אחרי try/catch בכל מקרה: אם הקוד הצליח, אם הוא זרק חריגה ואפילו אם הוא ביצע return מוקדם. זה המקום לניקוי שחייב לקרות תמיד, כמו סגירת קובץ או שחרור נעילה. לסגירת משאבים, try-with-resources בדרך כלל נקי יותר כי הוא סוגר אותם אוטומטית.

האם לתפוס Exception או טיפוס חריגה ספציפי?

תפסו את הטיפוס הספציפי ביותר שאתם באמת יודעים לטפל בו. תפיסה של Exception (או גרוע מזה, Throwable) בולעת כל בעיה, כולל באגים כמו NullPointerException, ומסתירה את הסיבה האמיתית. תפסו NumberFormatException אם זה מה שאתם מצפים לו, ותנו לחריגות לא צפויות להתפשט הלאה כדי שתדעו עליהן.

איור של שפות התכנות ב-Coddy

ללמוד תכנות עם Coddy

להתחיל