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

כפי שדנו בעבר ישנו Caching ל-string ו-int .

כלל זהב: לעולם לא נשתמש באופרטור == כדי להשוות בין אובייקטי Wrapper (כמו Integer או Boolean). השוואת אובייקטים מתבצעת תמיד בעזרת .equals()

⚠️ מלכודת NullPointerException ב Unboxing

מכיוון שטיפוס פרימיטיבי חייב להכיל ערך (לדוגמה 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
🏠 Back to Orly's Code Corner