Autoboxing & Unboxing
מנגנוני ה Autoboxing (אריזה אוטומטית) וה Unboxing (פריקה אוטומטית) הם פיצ'רים קריטיים ונוחים מאוד ב-Java שהוצגו לראשונה בJava 5. הם מאפשרים המרה אוטומטית ושקופה למתכנת בין הטיפוסים הפרימיטיביים (Primitive Types) לבין מחלקות המעטפת (Wrapper Classes) שלהם.
Autoboxing: המרה אוטומטית של טיפוס פרימיטיבי (כמו int, double, boolean) לאובייקט של מחלקת המעטפת המתאימה לו (כמו Integer, Double, Boolean).
Unboxing: המרה אוטומטית בכיוון ההפוך, מאובייקט מעטפת (כמו Integer) בחזרה לטיפוס הפרימיטיבי שלו (int).
מה קורה מאחורי הקלעים? (Bytecode) :
כמפתחים אנחנו נכתוב את הקוד הבא:
Integer x = 5;
int y = x;
הקומפיילר יהפוף את זה "מאחורי הקלעים"
Integer x = Integer.valueOf(5); // Autoboxing
int y = x.intValue(); // Unboxing
יצירת אובייקטים מיותרים (Garbage Collection): כל פעולת Autoboxing מייצרת אובייקט חדש ב-Heap (כל עוד הערך מחוץ לטווח ה Cache). בלולאות ארוכות, הדבר עלול ליצור מיליוני אובייקטים זמניים שיעמיסו על ה Garbage Collector (GC) ויגרמו להאטה (Memory Overhead).
הבדל מהירות: חישוב מתמטי על פרימיטיבי (int a = b + c;) מתבצע ישירות ברמת המעבד במיקרו שניות. חישוב על אובייקטים דורש פריקה (Unboxing), חישוב, ואז אריזה מחדש (Autoboxing), מה שאיטי משמעותית.
כפי שדנו בעבר ישנו Caching ל-string ו-int .
כלל זהב: לעולם לא נשתמש באופרטור == כדי להשוות בין אובייקטי Wrapper (כמו Integer או Boolean). השוואת אובייקטים מתבצעת תמיד בעזרת .equals()
מכיוון שטיפוס פרימיטיבי חייב להכיל ערך (לדוגמה int חייב להיות 0 ומעלה ולא יכול להיות null), Unboxing עלול להיכשל בקריסת מערכת אם האובייקט מכיל null.
Integer wrapperNum = null;
int primitiveNum = wrapperNum;
כלל זהב: תמיד לוודא שהאובייקט אינו null לפני ביצוע Unboxing או השוואות שעלולות לעורר אותו אוטומטית.
לפני JAVA 5 היינו צריכים לבצע ידנית, את ההמרה על הסוג משתנה:
List<Integer> list = new ArrayList<>();
list.add(Integer.valueOf(5));
int val = list.get(0).intValue();
היום (java 6 ומעלה), בזכות ה Autoboxing וה Unboxing, הקוד הופך לנקי ושקוף לחלוטין:
Integer wrappedInt = 5;
int primitiveInt = wrappedInt;
List<Integer> numbers = new ArrayList<>();
numbers.add(10);
int n = numbers.get(0);
טבלת ההתאמות (Primitives vs Wrappers):
| Primitive Type | Wrapper Class |
|---|---|
| byte | Byte |
| short | Short |
| int | Integer |
| long | Long |
| float | Float |
| double | Double |
| char | Character |
| boolean | Boolean |