Java String Pool
כפי שידוע לנו, לא נהוג לבדוק ערך של String על ידי == אלא על ידי
()equals.
הסיבה היא שהשוואת == בודקת האם מדובר באותו
מיקום בזיכרון (אותו reference).
אבל בכל זאת הדוגמה הבאה תחזיר לנו true:
String s1 = "hello java";
String s2 = "hello java";
System.out.println(s1 == s2);
System.out.println(s1.equals(s2));
אז מה בעצם קרה פה?
כמו ב-Integer Pool, גם String אינו מוזנח ב-Java. על מנת לחסוך בזיכרון ולנהל משאבים בצורה יעילה, Java שומרת String literals בתוך מאגר מיוחד הנקרא String Pool.
למידע נוסף על Integer Pool:
מה קורה כאשר משתמשים ב-new String?
אם ניצור String באמצעות new, ההשוואה באמצעות == לא תעבוד, מכיוון שהאובייקט החדש אינו משתמש ברפרנס שנמצא ב-String Pool.
String s3 = new String("hello java");
System.out.println(s2 == s3);
System.out.println(s2.equals(s3));
התוצאה תהיה:
- false עבור ==
- true עבור equals()
שימוש ב-()intern
אם נשתמש בפקודת ()intern, ההשוואה בשתי התצורות תחזיר true.
String s4 = s3.intern();
System.out.println(s2 == s4);
System.out.println(s2.equals(s4));
מה בעצם קרה כאן?
הפקודה ()intern ניגשת ל-String Pool ובודקת האם המחרוזת "hello java" כבר קיימת שם.
- אם היא קיימת - יוחזר הרפרנס הקיים מה-Pool.
- אם היא לא קיימת - היא תתווסף ל-Pool ויוחזר הרפרנס החדש.
שימוש לא נכון ב-()intern עלול להכביד על ה-String Pool ולפגוע בביצועים.
לדוגמה:
UUID.randomUUID().toString().intern();
הקוד הזה יכניס אלפי ערכים שונים ל-Pool ויגדיל אותו ללא צורך. מכיוון שכל UUID הוא ייחודי, אין סיבה אמיתית לשמור אותו ב-String Pool.
אז איך הזיכרון עובד?
ב-Java קיימים שני אזורי זיכרון עיקריים:
- Stack (מחסנית) - שומר משתנים מקומיים ורפרנסים לאובייקטים. מהיר מאוד לגישה.
- Heap (ערימה) - שומר את האובייקטים עצמם וכל מה שנוצר באמצעות new.
String Literal
String s1 = "hello java";
מה קורה בזיכרון?
- נוצר String ב-Heap.
- המחרוזת נשמרת גם ב-String Pool.
- המשתנה s1 ב-Stack מחזיק רפרנס לאובייקט.
└── s1 ───────────► "hello java"
String Pool
└── "hello java"
()new String
String s3 = new String("hello java");
כאן ייווצר אובייקט חדש לחלוטין ב-Heap.
└── s3 ───────────► Object #2
Heap
└── Object #2 = "hello java"
String Pool
└── "hello java"