Menu

Type Casting ב-Java: הרחבה, צמצום והמרות

איך Java ממירה בין טיפוסים: הרחבה אוטומטית, המרות צמצום מפורשות, אילו נתונים הולכים לאיבוד בצמצום, והמרה בין מספרים למחרוזות.

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

מה המשמעות של type casting

Java היא שפה עם טיפוסים סטטיים: לכל ערך יש טיפוס, והמהדר לא יאפשר לכם לערבב בשקט טיפוסים שאינם תואמים. Type casting הוא הדרך להמיר ערך מטיפוס אחד לאחר: לפעמים Java עושה את זה בשבילכם, ולפעמים צריך לבקש את זה במפורש.

יש שני כיוונים. מעבר מטיפוס קטן לטיפוס גדול יותר (int לתוך double) הוא בטוח וקורה אוטומטית. מעבר מטיפוס גדול לטיפוס קטן יותר (double לתוך int) עלול לאבד נתונים, ולכן Java מחייבת אתכם לכתוב את זה במפורש עם cast.

הרחבה: ההמרה האוטומטית

המרת הרחבה (widening) מעבירה ערך לטיפוס שיש בו יותר מקום. שום דבר לא יכול ללכת לאיבוד, ולכן Java עושה את זה בשבילכם בלי cast:

ה-int 7 נכנס לתוך double והופך ל-7.0. סדר ההרחבה של מספרים הוא byte -> short -> int -> long -> float -> double; השמה משמאל לימין לאורך השרשרת הזו אף פעם לא דורשת cast. זו הסיבה שערבוב טיפוסים בחישובים בדרך כלל "פשוט עובד": Java מרחיבה קודם את האופרנד הקטן יותר.

צמצום: ה-cast המפורש

בכיוון ההפוך, המרת צמצום (narrowing) עלולה להשמיט נתונים, ולכן המהדר מסרב אלא אם שמים את טיפוס היעד בסוגריים לפני הערך:

(int) pi הוא ה-cast. שימו לב מה הוא עושה: הוא חותך לכיוון אפס, ופשוט משליך את החלק העשרוני. 3.9 הופך ל-3, ו--3.9 הופך ל--3. הוא לא מעגל. אם רוצים לעגל, זה כלי אחר:

שכחה ש-cast חותך היא אחד הבאגים הנפוצים ביותר אצל מתחילים: אם המספר "המעוגל" שלכם תמיד יוצא קטן באחד, בדרך כלל זו הסיבה.

מלכודת החילוק בשלמים

המלכודת הזו תופסת את כולם לפחות פעם אחת. כששני האופרנדים הם int, האופרטור / מבצע חילוק בשלמים ומשליך את השארית, לפני שמתבצעת השמה כלשהי ל-double:

a / b הוא 7 / 2, שמחושב כולו בחשבון של int, ומתקבל 3. הרחבה ל-double אחר כך רק הופכת את 3 ל-3.0: ה-.5 כבר אבד. cast של אופרנד אחד ל-double קודם ((double) a / b) מכריח את כל הביטוי לעבור לנקודה צפה, ומתקבל ה-3.5 שרציתם. מספיק לבצע cast לצד אחד; Java מרחיבה את הצד השני כדי שיתאים.

כשצמצום גולש

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

300 לא נכנס ב-byte, ולכן הביטים העליונים מושלכים ומקבלים 44. זה איבוד נתונים "שקט": התוכנית רצה בלי בעיה ונותנת תשובה שגויה. צמצמו רק כשאתם בטוחים שהערך נכנס בטיפוס הקטן יותר.

המרה בין מספרים למחרוזות

String הוא אובייקט, לא מספר, ולכן אי אפשר לבצע עליו cast עם (int): זו שגיאת קומפילציה. במקום זה, ההמרה משתמשת במתודות ייעודיות:

מעבר מטקסט למספר משתמש ב-Integer.parseInt / Double.parseDouble. אם המחרוזת היא לא מספר תקין (למשל "hello"), המתודות האלה זורקות NumberFormatException. למעבר ממספר לטקסט, השתמשו ב-String.valueOf(n) או פשוט שרשרו עם "", כי n + "" מכריח את ה-int להפוך ל-String. שימו לב להבדל בין "5" + 1 (שנותן את המחרוזת "51") לבין 5 + 1 (שנותן 6); ה-+ הופך לשרשור ברגע שמעורב String.

cast של אובייקטים

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

Object o = "hello";
String s = (String) o;        // תקין: o באמת מפנה ל-String
Integer bad = (Integer) o;    // מתקמפל, אבל זורק ClassCastException בזמן ריצה

ה-cast השני מתקמפל אבל קורס בזמן ריצה עם ClassCastException, כי האובייקט הוא String ולא Integer. תכירו את זה לעומק כשתגיעו לירושה ולפולימורפיזם; בינתיים, מספיק לדעת שתחביר ה-(Type) הוא אותו רעיון שמוחל על אובייקטים.

שאלות נפוצות

מה זה type casting ב-Java?

Type casting הוא המרה של ערך מטיפוס נתונים אחד לאחר. Java מבצעת בעצמה המרות "הרחבה" קטנות (כמו מ-int ל-double), אבל המרת "צמצום" שעלולה לאבד נתונים (כמו מ-double ל-int) דורשת cast מפורש: int n = (int) 3.9;.

איך ממירים double ל-int ב-Java?

כותבים את טיפוס היעד בסוגריים לפני הערך: int n = (int) 3.9;. הפעולה חותכת לכיוון אפס (משמיטה את החלק העשרוני), כך שמקבלים 3 ולא 4. כדי לעגל במקום זה, השתמשו ב-Math.round(3.9), שמחזירה 4.

איך ממירים String ל-int ב-Java?

String הוא לא מספר, ולכן אי אפשר לבצע עליו cast עם (int). השתמשו ב-Integer.parseInt("42") כדי לקבל int, או ב-Double.parseDouble("3.14") עבור double. אם הטקסט הוא לא מספר תקין, המתודות האלה זורקות NumberFormatException.

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

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

להתחיל