JavaRush /בלוג Java /Random-HE /עוטפים, פורקים ואריזות

עוטפים, פורקים ואריזות

פורסם בקבוצה
שלום! אתה כבר די מכיר טיפוסים פרימיטיביים, ועבדת איתם הרבה. עטיפה, פריקה ואריזה - 1לפרימיטיבים בתכנות, וב-Java בפרט, יש יתרונות רבים: הם תופסים מעט זיכרון, ובכך מגדילים את היעילות של התוכנית, ומחולקים בבירור לטווחי ערכים. עם זאת, בתהליך לימוד Java, חזרנו יותר מפעם אחת, כמו מנטרה, " ב-Java הכל הוא אובייקט ." אבל פרימיטיביים הם הפרכה ישירה של המילים הללו. הם לא חפצים. אז העיקרון "הכל חפץ" הוא שקרי? לא באמת. בג'אווה, לכל טיפוס פרימיטיבי יש את אחיו התאום, מחלקת העטיפה ( Wrapper). מה זה עטיפה? עטיפה היא מחלקה מיוחדת המאחסנת את הערך של פרימיטיבי בתוך עצמו. אבל מכיוון שזו מחלקה, היא יכולה ליצור מופעים משלה. הם יאחסנו את הערכים הפרימיטיביים הדרושים בפנים, תוך שהם אובייקטים אמיתיים. שמות כיתות העטיפה דומים מאוד לשמות הפרימיטיביים המקבילים, או עולים בקנה אחד איתם לחלוטין. לכן, יהיה קל מאוד לזכור אותם.
שיעורי עטיפה לסוגי נתונים פרימיטיביים
סוגי נתונים פרימיטיביים שיעורי עטיפה
int מספר שלם
קצר קצר
ארוך ארוך
בייט בייט
לָצוּף לָצוּף
לְהַכפִּיל לְהַכפִּיל
לְהַשְׁחִיר אופי
בוליאני בוליאנית
אובייקטים בכיתה Wrapper נוצרים בדיוק כמו כל אובייקט אחר:
public static void main(String[] args) {

   Integer i = new Integer(682);

   Double d = new Double(2.33);

   Boolean b = new Boolean(false);
}
שיעורי עטיפה מאפשרים לך להפחית את החסרונות שיש לטיפוסים פרימיטיביים. הברור ביותר הוא שלפרימיטיבים אין שיטות . לדוגמה, אין להם שיטה toString(), כך שאתה לא יכול, למשל, להמיר מספר intלמחרוזת. אבל עם שיעור עטיפה Integerזה קל.
public static void main(String[] args) {

   Integer i = new Integer(432);

   String s = i.toString();
}
יהיו גם קשיים עם הטרנספורמציה ההפוכה. נניח שיש לנו מחרוזת שאנחנו יודעים בוודאות שמכילה מספר. עם זאת, במקרה של טיפוס פרימיטיבי, intלא נוכל לקבל את המספר הזה מהמחרוזת ולהפוך אותו, למעשה, למספר. אבל הודות לשיעורי עטיפה, יש לנו כעת את ההזדמנות הזו.
public static void main(String[] args) {

   String s = "1166628";

   Integer i = Integer.parseInt(s);

   System.out.println(i);
}
פלט: 1166628 שלפנו בהצלחה מספר ממחרוזת והקצנו אותו למשתנה התייחסות Integer i. אגב, לגבי קישורים. אתה כבר יודע שפרמטרים מועברים לשיטות בדרכים שונות: פרימיטיביים מועברים לפי ערך, ואובייקטים מועברים באמצעות הפניה. אתה יכול להשתמש בידע הזה בעת יצירת השיטות שלך: אם השיטה שלך עובדת, למשל, עם מספרים שברים, אבל אתה צריך את ההיגיון של העברה באמצעות הפניה, אתה יכול להעביר פרמטרים לשיטה Double/Floatבמקום double/float. בנוסף, בנוסף לשיטות, לשיעורי עטיפה יש שדות סטטיים שמאוד נוחים לשימוש. לדוגמה, דמיין שעומדת בפניך כעת משימה: הדפס את המספר המקסימלי האפשרי לקונסולה intולאחר מכן את המספר המינימלי האפשרי. נראה שהמשימה היא בסיסית, אבל עדיין, בקושי תוכל לעשות אותה בלי גוגל. ושיעורי עטיפה מאפשרים לך לפתור בקלות את ה"בעיות היומיומיות" הבאות:
public class Main {
   public static void main(String[] args) {

       System.out.println(Integer.MAX_VALUE);
       System.out.println(Integer.MIN_VALUE);
   }
}
שדות כאלה מאפשרים לך לא להיות מוסחת ממשימות רציניות יותר. שלא לדבר על העובדה שבתהליך הדפסת המספר 2147483647 (זה בדיוק MAX_VALUE) לא מפתיע להקליד אותו בצורה שגויה :) בנוסף, באחת ההרצאות הקודמות כבר הפנינו את תשומת הלב לעובדה שאובייקטים של שיעורי עטיפה בלתי ניתנים לשינוי .
public static void main(String[] args) {

   Integer a = new Integer(0);
   Integer b = new Integer(0);

   b = a;
   a = 1;
   System.out.println(b);
}
פלט: 0 האובייקט שההפניה הצביעה עליו במקור аלא שינה את מצבו, אחרת גם הערך bהיה משתנה. כמו עם String, במקום לשנות את מצב אובייקט העטיפה, נוצר אובייקט חדש לגמרי בזיכרון. מדוע החליטו יוצרי Java בסופו של דבר לשמור על טיפוסים פרימיטיביים בשפה? מכיוון שהכל צריך להיות אובייקט, וכבר יש לנו שיעורי עטיפה שאפשר לבטא את כל מה שהפרימיטיביים מבטאים, למה לא פשוט להשאיר אותם בשפה ולהסיר את הפרימיטיביים? התשובה פשוטה - ביצועים. טיפוסים פרימיטיביים נקראים פרימיטיביים מכיוון שהם נטולי תכונות "כבדות" רבות של חפצים. כן, לחפץ יש הרבה שיטות נוחות, אבל לא תמיד צריך אותן. לפעמים אתה רק צריך את המספר 33, או 2.62, או את הערך של true/ false. במצבים שבהם כל היתרונות של אובייקטים אינם רלוונטיים ואינם נחוצים כדי שהתוכנית תעבוד, פרימיטיביים יעשו עבודה הרבה יותר טובה.

אריזה אוטומטית / פריקה אוטומטית

אחד המאפיינים של פרימיטיביים ושיעורי העטיפה שלהם בג'אווה הוא אוטובוקסינג/אוטואונבוקסינג. עטיפה, פריקה ואריזה - 2 בואו נבין את המושג הזה. כפי שאתה ואני כבר למדנו קודם לכן, ג'אווה היא שפה מונחה עצמים. המשמעות היא שכל התוכנות שנכתבות ב-Java מורכבות מאובייקטים. פרימיטיבים אינם אובייקטים. עם זאת, ניתן להקצות למשתנה מחלקת העטיפה ערך מסוג פרימיטיבי. תהליך זה נקרא אוטובוקסינג . באותו אופן, ניתן להקצות למשתנה מסוג פרימיטיבי אובייקט של מחלקת עטיפה. תהליך זה נקרא autounboxing . לדוגמה:
public class Main {
   public static void main(String[] args) {
       int x = 7;
       Integer y = 111;
       x = y; // auto unpacking
       y = x * 123; // autopacking
   }
}
בשורה 5, אנו מקצים ל-x הפרימיטיבי את הערך של y, שהוא אובייקט של מחלקת העטיפה Integer. כפי שאתה יכול לראות, אין צורך בפעולות נוספות לשם כך: המהדר יודע זאת , intולמעשה Integer, אותו דבר . זוהי פריקה אוטומטית. אותו דבר קורה עם אוטובוקסינג בשורה 6: לאובייקט y ניתן בקלות ערך של פרימיטיביים (x*123). זו דוגמה לאריזה אוטומטית. זו הסיבה שהמילה "אוטומטי" מתווספת: כדי להקצות הפניות פרימיטיביות לאובייקטים של מחלקות העטיפה שלהם (ולהיפך) אתה לא צריך לעשות כלום, הכל קורה אוטומטית . נוח, נכון? :) עוד נוחות מאוד גדולה של אריזה אוטומטית/פריקה אוטומטית באה לידי ביטוי בתפעול השיטות. העובדה היא שפרמטרי השיטה כפופים גם לאריזה אוטומטית ולפריקה אוטומטית . ולדוגמה, אם אחד מהם לוקח שני אובייקטים כקלט Integer, נוכל להעביר לשם בקלות פרימיטיבים רגילים int!
public class Main {
   public static void main(String[] args) {

       printNumber(7);//regular int, even without a variable
   }

   public static void printNumber(Integer i) {
       System.out.println("You entered a number" + i);
   }
}
פלט: הזנת את המספר 7. זה עובד הפוך:
public class Main {
   public static void main(String[] args) {

       printNumber(new Integer(632));
   }

   public static void printNumber(int i) {
       System.out.println("You entered a number" + i);
   }
}
נקודה חשובה שיש לזכור: אוטובוקסינג ו-unboxing לא עובדים עבור מערכים !
public class Main {
   public static void main(String[] args) {

       int[] i = {1,2,3,4,5};

       printArray(i);//error, won't compile!
   }

   public static void printArray(Integer[] arr) {
       System.out.println(Arrays.toString(arr));
   }
}
ניסיון להעביר מערך של פרימיטיבים לשיטה שלוקחת מערך של אובייקטים כקלט יגרום לשגיאת קומפילציה. לבסוף, בואו נשווה שוב בקצרה פרימיטיביות ופרימיטיביות עטיפות:
  • בעלי יתרון ביצועים
עטיפות:
  • הם מאפשרים לך לא להפר את העיקרון "הכל הוא אובייקט", כדי שמספרים, סמלים וערכים בוליאניים נכונים/לא יפלו מהמושג הזה
  • הרחב את היכולת לעבוד עם ערכים אלו על ידי מתן שיטות ותחומים נוחים
  • הכרחי כאשר שיטה כלשהי יכולה לעבוד אך ורק עם אובייקטים
הערות
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION