在Java中字符串(String)是一個不可改變的類。一個不可改變的類只是一個對象實例不可修改的簡單類。當創建一個對象實例時,對象實例的所有信息都被初始化,并且信息不能被修改。對于不可改變的類來說還有很多優勢。上一篇文章很好說明了為什么字符串被設計成不可改變的。只有你很好的掌握了內存,同步,數據結構等知識后,你才能很好的回答這個問題。
1.字符串常量池的需求
字符串常量區是方法區(Method Area)中一塊特殊的存儲區域。當一個字符串被創建,如果該字符串已經存在字符串常量區時,相應的返回存在字符串的引用,而不是去新創建一個新的對象返回它的引用。
下面的代碼中只會在堆中創建一個字符串對象。
~~~
String string1 = "abcd";
String string2 = "abcd";
~~~
下面的圖能很好的說明:

如果字符串是可以改變的,改動一個字符串的引用將會導致另一個引用出現錯誤值。
2.緩存HashCode(哈希碼)
在Java中一個字符串的哈希碼是經常被使用的,例如在hashMap中。不可改變性確保了哈希碼總是會保持不變,這樣我們就不必擔心發生任何變化。換一句話說,我們沒有必要每次使用字符串時都要計算哈希碼(因為不可改變性確保哈希碼保持不變),這是一種更有效率的方式。
在String類中,都會有下列代碼:
~~~
public final class String implements java.io.Serializable, Comparable<String>, CharSequence{
/** 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是可變的,那么其值就可以修改,這有違集(set)的設計(集中不包含重復的元素)。這個例子為簡單考慮,在真實String類中沒有value屬性。
4.安全
String在很多Java類中廣泛使用作為參數,例如,網絡連接,打開文件等等。如果字符串是可改變的,那么網絡連接或者文件都可能會被改變,將導致嚴重的安全威脅。方法還以為是連接到一臺機器上,但實際上卻沒有。可變字符串可能會導致在反射中出現問題,因為這些參數都是字符串。
~~~
boolean connect(string s){
if (!isSecure(s)) {
throw new SecurityException();
}
//如果在這之前s通過其他引用進行改變,這可能會出現問題
causeProblem(s);
}
~~~
5.不可變對象是線程安全的
因為不可變對象是不可改變的,那么它們可以在多個線程之間自由的共享。這就取消了進行同步的需求。
總之,字符串被設計為不可變是為了效率和安全性考慮。這也就是一般情況下優先選擇不可變對象的原因。
原文:[Why String is immutable in Java ?](http://www.programcreek.com/2013/04/why-string-is-immutable-in-java/)
- 前言
- [Hibernate開發之路](1)Hibernate配置
- [Hibernate開發之路](2)Hibernate問題
- [Hibernate開發之路](3)基礎配置
- [Hibernate開發之路](4)ID生成策略
- [Hibernate開發之路](5)聯合主鍵
- [設計模式實踐之路](1)單例模式
- [Java]UDP通信的簡單例子
- [Java]套接字地址InetAddress講解
- [Java開發之路](1)final關鍵字
- [Java開發之路](2)Java字符串
- [Java開發之路](3)Java常用類
- [Java開發之路](4)String、StringBuffer與StringBuilder詳解
- [Java開發之路](5)異常詳解
- [Java開發之路](6)File類的使用
- [Java開發之路](7)RandomAccessFile類詳解
- [Java開發之路](8)輸入流和輸出流
- [Java開發之路](9)對象序列化與反序列化
- [Java開發之路](10)DOM解析XML文檔
- [Java開發之路](11)SAX解析XML文檔
- [Java開發之路](12)JDOM和DOM4J解析XML文檔
- [Java開發之路](14)反射機制
- [Java開發之路](15)注解
- [Java開發之路](16)學習log4j日志
- [Java開發之路](18)關于Class.getResource和ClassLoader.getResource的路徑問題
- [Java開發之路](19)Long緩存問題
- [Java開發之路](20)try-with-resource 異常聲明
- [Java開發之路](21)Comparator與Comparable
- [Java]Java工程師成神之路
- [細說Java](1)圖說字符串的不變性
- [細說Java](2)Java中字符串為什么是不可變的
- [細說Java](3)創建字符串是使用&quot; &quot;還是構造函數?