מה אופרטורים עושים
אופרטורים הם הסמלים שמשלבים ערכים כדי לחשב ערכים חדשים. אתם כבר משתמשים בהם באופן אינטואיטיבי: + מחבר, > משווה. Java מחלקת אותם לכמה משפחות: חשבון, השוואה, לוגיקה, השמה, ועוד כמה מיוחדים כמו הגדלה והאופרטור הטרנרי.
רוב האופרטורים מקבלים שני ערכים (אחד לפני הסמל ואחד אחריו) ומפיקים תוצאה. החוכמה היא לדעת מה הטיפוס של התוצאה ובאיזה סדר הם מופעלים, ושם מתחילים נתקלים.
אופרטורים חשבוניים
חמשת האופרטורים החשבוניים פועלים על מספרים: +, -, *, / ו-% (שארית).
האופרטור % הוא השארית אחרי חלוקה: 17 % 5 הוא 2 כי 5 נכנס ב-17 שלוש פעמים ונשארים 2. זה הכלי היומיומי לבדיקת התחלקות: n % 2 == 0 היא הבדיקה המקובלת ל"האם n זוגי?".
שימו לב גם ש-+ עושה עבודה כפולה: עם מספרים הוא מחבר, אבל כשיש String באחד הצדדים הוא מחבר טקסט.
השורה הראשונה מחושבת לפי הסדר, מההתחלה לסוף: "Total: " + 3 הוא כבר מחרוזת, ולכן ה-4 מצורף כטקסט. עטפו את החישוב בסוגריים כשרוצים שהוא יחושב קודם.
המלכודת של חלוקת שלמים
זו ההפתעה הנפוצה ביותר. כששני האופרנדים של / שלמים, Java מבצעת חלוקת שלמים ומשליכה את השבר: היא לא מעגלת, היא קוטעת לכיוון אפס.
כדי לקבל תוצאה עשרונית, הפכו לפחות אופרנד אחד ל-double: או כתבו אותו עם .0, או המירו צד אחד עם (double). ההמרה (double)(5 / 2) לא עוזרת, כי חלוקת השלמים 5 / 2 כבר התבצעה לפני ההמרה; צריך להמיר אופרנד, לא את התוצאה.
אופרטורי השוואה
אופרטורי השוואה שואלים שאלת כן או לא ומחזירים boolean. יש שישה: ==, !=, <, >, <=, >=.
שימו לב להבדל בין = (השמה: "שים את הערך הזה כאן") לבין == (השוואה: "האם אלה שווים?"). בלבול ביניהם הוא באג קלאסי.
הסתייגות חשובה אחת: == משווה הפניות של אובייקטים, לא תוכן. במחרוזות, השתמשו ב-.equals().
השתמשו ב-== לטיפוסים פרימיטיביים כמו int ו-boolean, וב-.equals() בכל פעם שמשווים תוכן של אובייקטים כמו מחרוזות.
אופרטורים לוגיים
אופרטורים לוגיים משלבים ערכים בוליאניים: && (וגם), || (או) ו-! (לא). כך מבטאים תנאים כמו "מבוגר מספיק וגם יש לו כרטיס".
&& ו-|| מבצעים הערכה מקוצרת (short-circuit): Java מפסיקה לחשב ברגע שהתשובה ודאית. עם &&, אם האופרנד הראשון הוא false, השני לא נבדק בכלל; עם ||, אם האופרנד הראשון הוא true, השני מדולג. זה לא רק אופטימיזציה, אפשר לסמוך על זה לבטיחות:
if (text != null && text.length() > 0) { ... }
אם text הוא null, האופרנד הראשון הוא false ו-text.length() לא נקראת, וכך נמנעת NullPointerException. אם הופכים את הסדר, התוכנית קורסת.
השמה והגדלה
= משים, אבל ל-Java יש גם השמות מורכבות שמשלבות פעולה עם השמה: +=, -=, *=, /=, %=. ו-++ / -- מוסיפים או מחסירים אחד.
++ מגיע בשתי גרסאות: postfix (count++) מחזיר את הערך הישן ואז מגדיל; prefix (++count) מגדיל קודם ואז מחזיר את הערך החדש. ההבדל חשוב רק כשמשתמשים בתוצאה באותו ביטוי:
כש-++ עומד בשורה משלו, אין הבדל בין postfix ל-prefix, אז העדיפו את מה שנקרא בבהירות ואל תדחסו הגדלות לתוך ביטויים גדולים יותר.
האופרטור הטרנרי
הטרנרי condition ? a : b הוא if/else קומפקטי שמפיק ערך: אם התנאי true הוא מחושב ל-a, אחרת ל-b.
הוא מצטיין בהשמות קצרות של או זה או זה. אל תקננו טרנרי בתוך טרנרי: זה נהיה לא קריא מהר מאוד, ו-if/else רגיל ברור יותר.
קדימות וסוגריים
אופרטורים מופעלים בסדר קבוע, בדומה למתמטיקה: *, /, % נקשרים חזק יותר מ-+ ו--, שנקשרים חזק יותר מהשוואות, שנקשרות חזק יותר מ-&&, ואחריו ||.
לא צריך לשנן את הטבלה המלאה. כשביטוי מערבב משפחות או כשצריך לעצור כדי להבין את הסדר, הוסיפו סוגריים: הם לא עולים כלום והופכים את הכוונה לברורה לקורא הבא.
הבא: המרת טיפוסים
כמה מהמלכודות כאן, חלוקת שלמים וערבוב של int ו-double, מסתכמות בטיפוסים. המרה מכוונת בין טיפוסי מספרים נקראת casting, וזה העמוד הבא.
שאלות נפוצות
מה עושה האופרטור % ב-Java?
% הוא אופרטור השארית (מודולו): הוא נותן את מה שנשאר אחרי חלוקת שלמים. 7 % 3 הוא 1, ו-10 % 2 הוא 0. זו הדרך המקובלת לבדוק התחלקות (n % 2 == 0 פירושו ש-n זוגי) ולגלגל ערך לתוך טווח.
למה 5 / 2 נותן 2 ב-Java ולא 2.5?
כששני האופרנדים שלמים, / מבצע חלוקת שלמים ומשליך את החלק השברי, כך ש-5 / 2 הוא 2, לא 2.5. כדי לקבל 2.5 צריך שלפחות אופרנד אחד יהיה double: כתבו 5.0 / 2, 5 / 2.0, או המירו צד אחד עם (double) 5 / 2.
מה ההבדל בין == ל-equals() ב-Java?
== משווה טיפוסים פרימיטיביים לפי ערך, אבל באובייקטים (כולל String) הוא משווה הפניות: האם מדובר באותו אובייקט בזיכרון. כדי להשוות את התוכן של אובייקטים, משתמשים ב-.equals(). השוואה של שתי מחרוזות עם == עלולה להחזיר false גם כשהטקסט זהה, ולכן במחרוזות תמיד השתמשו ב-"a".equals(b).