String and String Pool

String Immutable

Java 中的字串一旦宣告,他就不會再被變動了,這樣設計主要有三個理由:

  • String Pool 的需求:當把多個變數指到一樣的內容的 String 上,萬一 String 不是一個 Imutable,就會發生這個 Reference 去改值,另一個也會受到影響。
  • 確保 String Hash Code 是不變的: String 的 HashCode 是常常被調用的,在 HashMap 中,必須確保
  • 安全性 – String 常常帶有一些敏感性的資訊,像是密碼或是其它資料,可能會被寫入資料庫或檔案,一旦可以一直被變動,就可能會延伸不必要的風險。

String Pool

Java 中 String 是常常在操作的類別,字串在記憶體的管理上有一點點的特殊, 當透過 String name = "Balicanta"; 來宣告一個字串的時候,其實會到 String Pool 裡面找是否有一樣的字串,如果有那就不會去建立一個新的字串,而會讓兩個 reference 指到同一個位置,以確保 memory 使用的效率。

System.identityHashCode 作用

這個方法的作用是,找到一個 Object 的 HashCode。意思是說常常會複寫掉 Object 提供的 hashcode,讓我們看不出 Object 的 hashCode 是什麼,identityHashCode 可以直接印出 Object 的 HashCode,所以可以透過 identityHashCode 來驗證是否真的有 String Pool 的概念。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
String stringA = new String("them");
System.out.println(System.identityHashCode(stringA)); //6391841
System.out.println(stringA.hashCode()); // 3558940

String stringP = new String("them");
System.out.println(System.identityHashCode(stringP)); // 25246738
System.out.println(stringP.hashCode()); // 3558940

String stringB = "them";
System.out.println(System.identityHashCode(stringB)); // 26140476
System.out.println(stringB.hashCode()); // 3558940

String stringC = "them";
System.out.println(System.identityHashCode(stringC)); // 26140476
System.out.println(stringC.hashCode()); // 3558940

上面的例子說明幾件事:

  • String.hashCode 是無法分辨,String 實際的位置,必須透過 identityHashCode 。
  • 透過 new String(“xxx”) 的確會產生出不一樣的物件,不是透過 String Pool 來取得。

補充

在過去 JDK 6 String Pool 是會占用 PermGen 的空間,但從 JDK 7 開始把 String Pool 放到 Heap 裡面。

Reference: Why String is Immutable