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:

  • Java Int Pool
  • מה קורה כאשר משתמשים ב-new String?

    אם ניצור String באמצעות new, ההשוואה באמצעות == לא תעבוד, מכיוון שהאובייקט החדש אינו משתמש ברפרנס שנמצא ב-String Pool.

    String s3 = new String("hello java");
    
    System.out.println(s2 == s3);
    System.out.println(s2.equals(s3));

    התוצאה תהיה:

    שימוש ב-()intern

    אם נשתמש בפקודת ()intern, ההשוואה בשתי התצורות תחזיר true.

    String s4 = s3.intern();
    
    System.out.println(s2 == s4);
    System.out.println(s2.equals(s4));

    מה בעצם קרה כאן?

    הפקודה ()intern ניגשת ל-String Pool ובודקת האם המחרוזת "hello java" כבר קיימת שם.

    שימו לב:
    שימוש לא נכון ב-()intern עלול להכביד על ה-String Pool ולפגוע בביצועים.

    לדוגמה:

    UUID.randomUUID().toString().intern();

    הקוד הזה יכניס אלפי ערכים שונים ל-Pool ויגדיל אותו ללא צורך. מכיוון שכל UUID הוא ייחודי, אין סיבה אמיתית לשמור אותו ב-String Pool.

    אז איך הזיכרון עובד?

    ב-Java קיימים שני אזורי זיכרון עיקריים:

    String Literal

    String s1 = "hello java";

    מה קורה בזיכרון?

    Stack
    └── s1 ───────────► "hello java"

    String Pool
    └── "hello java"

    ()new String

    String s3 = new String("hello java");

    כאן ייווצר אובייקט חדש לחלוטין ב-Heap.

    Stack
    └── s3 ───────────► Object #2

    Heap
    └── Object #2 = "hello java"

    String Pool
    └── "hello java"
    למידע נוסף על הבדלים בזיכרון בין JAVA7 ל JAVA8 ניתן לקרוא כאן

    🏠 Back to Orly's Code Corner