字符串常量池簡介

爲什麼Java中的String類是不可變的?

String類是Java中的一個不可變類immutable class)。

簡單來說,不可變類就是實例在被創建之後不可修改。

《Effective Java》 Item 15 中提到了爲了使類成爲不可變,需要遵循的五條規則:

  1. 不要提供任何會修改對象狀態的方法。

  2. 保證類不會被擴展。

  3. 使所有的域都是final的。

  4. 使所有域都成爲私有的。

  5. 確保對於任何可變組件的互斥訪問。

不可變類有許多優點,不可變類比可變類更加易於設計、實現和使用,不容易出錯,且更加安全。

下面來看一下Java把String類設計爲不可變類的幾個原因:

1. 由於字符串池的存在

字符串池(String Pool)是方法區中的一塊存儲空間,當創建一個字符串時,如果池中已經存在相同的字符串就會返回其引用,而不是在堆中創建一個新對象。(此處指的是字面量創建字符串,用new關鍵字創建的話,無論池中存不存在都會在堆中創建一個新對象)

String string1 = "abcd";
String string2 = "abcd";

如果字符串是可變的話,通過一個引用改變它的值,將會導致其他引用的值也同樣改變,從而可能發生錯誤。

2. 緩存hashcode

Java中經常用到一個字符串的hashcode,如在HashMap和HashSet中。不可變性保證同一個字符串對象的hashcode總是相同的,而在使用時不用考慮其是否發生改變。

這意味着不需要每次都計算一遍hashcode,使程序更加高效。

/** Cache the hash code for the string */
private int hash; // Default to 0
3. 保證其他對象的使用

爲了具體一點,舉一個栗子。

複製代碼
HashSet<String> set = new HashSet<String>();
set.add(new String("a"));
set.add(new String("b"));
set.add(new String("c"));

for(String a: set)
a.value
= “a”;

複製代碼

 在這個例子中,如果String是可變的話將破壞HashSet(集合中可能會包含重複元素)。

4. 安全性

在Java中String被用作許多方法的參數,例如網絡連接,對文件的操作等等。

假如String不是不可變的,一個連接或文件將可能被改變,這會產生嚴重的安全隱患。

因爲Java中反射的參數也是字符串,所以可變字符串同樣會產生安全問題。

下面是一個例子:

複製代碼
boolean connect(string s){
    if (!isSecure(s)) { 
throw new SecurityException(); 
}
    //here will cause problem, if s is changed before this by using other references.    
    causeProblem(s);
}
複製代碼
5. 不可變對象自然是線程安全的

不可變對象是線程安全的,它們可以被自由地共享,不要求同步。

 

不可變類的優勢有很多,當然也有缺點,就是對於每個不同的值都需要一個單獨的對象。


6.參考鏈接
http://www.cnblogs.com/justcooooode/p/7514863.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章