קבלת החלטות עם if
תוכניות צריכות להגיב לנתונים: עבר או נכשל, במלאי או אזל, תקין או לא. משפט ה-if הוא הדרך של Java לבחור איזה קוד להריץ לפי תנאי.
if מקבל תנאי בוליאני בסוגריים ומריץ את הבלוק שבסוגריים המסולסלים רק כשהתנאי הוא true:
התנאי score >= 60 הוא true, ולכן ההודעה מודפסת. השורה שאחרי הסוגר המסולסל הסוגר תמיד רצה: היא מחוץ ל-if. שנו את score ל-40 ושורת ה-"passed" תדולג לגמרי.
בניגוד ל-C, Java לא מאפשרת לשים מספר במקום שבו צריך בוליאני. if (score) היא שגיאת קומפילציה: התנאי חייב להיות ביטוי boolean אמיתי שבנוי מהשוואות (>, >=, ==, !=) או מלוגיקה בוליאנית (&&, ||, !).
הוספת else
else נותן לכם את מסלול ה-"אחרת": קוד שרץ רק כשהתנאי הוא false:
בדיוק אחד משני הבלוקים רץ: אף פעם לא שניהם, ואף פעם לא אף אחד. ל-else אין תנאי משלו; הוא פשוט תופס את כל מה שה-if לא תפס.
שרשור עם else if
כשיש יותר משתי תוצאות אפשריות, שרשרו תנאים עם else if. Java בודקת אותם לפי הסדר, מהראשון לאחרון, ומריצה את הבלוק הראשון שהתנאי שלו true, ואז מדלגת על כל השאר:
הסדר חשוב. מכיוון ש-84 נבדק קודם מול >= 90 (false), ואז מול >= 80 (true), הבדיקה נעצרת ב-B ואפילו לא מגיעה לגבולות הנמוכים. בגלל זה גם לא צריך לכתוב score >= 80 && score < 90: ההגעה לענף השני כבר מבטיחה ש-score היה מתחת ל-90. שימו ראשון את התנאי הצר ביותר או בעל העדיפות הגבוהה ביותר.
ה-else בסוף הוא התופס-הכול שלכם. השמטה שלו כאן הייתה שגיאת קומפילציה, כי ייתכן ש-grade עוד לא קיבל ערך כשמדפיסים אותו.
השוואת ערכים: == מול equals()
הבאג הנפוץ ביותר במשפטי if ב-Java הוא השוואת מחרוזות עם ==. לטיפוסים פרימיטיביים (int, double, char, boolean) == הוא הנכון. לאובייקטים, == שואל "האם זה אותו אובייקט בזיכרון?", ואילו .equals() שואל "האם יש להם אותו תוכן?", וכמעט תמיד רוצים את השני:
רק ההודעה השנייה מודפסת. new String("yes") הוא אובייקט שונה מהליטרל "yes", ולכן == הוא false, אבל הטקסט זהה, ולכן .equals() הוא true. כלל אצבע: פרימיטיביים משתמשים ב-==, אובייקטים משתמשים ב-.equals().
טריק בטוח אחד כדי להימנע מ-NullPointerException כשהמשתנה עשוי להיות null: שימו את הליטרל ראשון, if ("yes".equals(input)), כי ליטרל אף פעם לא null.
שילוב וקינון של תנאים
אפשר לשלב תנאים עם && (וגם), || (או) ו-! (לא), או לקנן if אחד בתוך אחר כשבדיקה הגיונית רק אחרי שבדיקה קודמת עברה:
&& ו-|| מבצעים short-circuit: ב-a && b, אם a הוא false, Java אף פעם לא מחשבת את b. זה שימושי להגנה מפני שגיאות: if (s != null && s.length() > 0) בטוח, כי בדיקת האורך מדולגת כש-s הוא null. כשאפשר, העדיפו שילוב עם && על פני קינון עמוק; קוד שטוח קריא יותר מפירמידה של סוגריים.
מלכודת קלאסית: = בודד הוא השמה, == הוא השוואה. כתיבת if (x = 5) היא שגיאת קומפילציה עבור int (טוב), אבל if (flag = true) על boolean מתקמפל ומשים בשקט: שימו לב לזה.
האופרטור הטרנרי
כשכל מה שרוצים הוא לבחור בין שני ערכים, האופרטור הטרנרי ?: הוא שורה אחת קומפקטית. קראו את condition ? a : b כ-"אם condition אז a, אחרת b":
האופרטור הטרנרי מייצר ערך שאפשר להשים או להעביר ישירות. שמרו אותו לבחירה פשוטה: אם אחד הענפים צריך כמה פקודות או לוגיקה אמיתית, if-else מלא נשאר קריא, ואילו אופרטור טרנרי מקונן הופך מהר לחידה.
מלכודת: הסוגריים המסולסלים האופציונליים
Java מאפשרת לוותר על הסוגריים המסולסלים כשבענף יש פקודה אחת, אבל זה מזמין באג עדין. ההזחה משקרת:
if (loggedIn)
System.out.println("Welcome");
System.out.println("Loading dashboard"); // NOT part of the if!
רק השורה הראשונה נשלטת על ידי ה-if; השנייה רצה תמיד, למרות שההזחה רומזת אחרת. השתמשו תמיד בסוגריים מסולסלים, גם לשורה אחת, וכל סוג הטעויות הזה נעלם.
הבא בתור: switch
שרשראות if-else if מושלמות כשכל ענף בודק תנאי אחר. אבל כשבודקים ערך אחד מול הרבה אפשרויות קבועות, שם של יום, בחירה בתפריט, enum, סולם ארוך של else if נהיה חזרתי. משפט ה-switch נבנה בדיוק בשביל זה, וזה העמוד הבא.
שאלות נפוצות
איך כותבים משפט if-else ב-Java?
שמים תנאי בוליאני בסוגריים אחרי if, ואז את הקוד להרצה בסוגריים מסולסלים, ובלוק else אופציונלי למקרה שהתנאי false: if (score >= 60) { System.out.println("Pass"); } else { System.out.println("Fail"); }. התנאי חייב להיות מטיפוס boolean: Java לא תקבל int כמו ש-C מקבלת.
מה ההבדל בין == ל-equals() במשפט if ב-Java?
== בודק אם שתי הפניות מצביעות על אותו אובייקט, ואילו .equals() משווה את התוכן. לטיפוסים פרימיטיביים כמו int השתמשו ב-==. לאובייקטים, ובמיוחד ל-String, השתמשו ב-.equals(): if (name.equals("Sam")), לא if (name == "Sam"). שימוש ב-== על מחרוזות הוא הבאג הנפוץ ביותר במשפטי if ב-Java.
מה זה האופרטור הטרנרי ב-Java?
האופרטור הטרנרי condition ? valueIfTrue : valueIfFalse הוא if-else קומפקטי שמחזיר ערך. למשל String label = age >= 18 ? "adult" : "minor"; משים אחד משני ערכים לפי התנאי. השתמשו בו לבחירת ערך פשוטה; עברו ל-if-else מלא כשיש לוגיקה להריץ בכל ענף.