Normally,you create an object and allow its contents to be changed later.However ,occasionally it is desirable to create an object whose contents cannot be changed once the object has been created.We call such an object as immutable object and its class as immutable class.html
建立一個一旦其內容就不能在改變的對象,稱其爲一個不可變對象(immutable object),而它的類稱爲不可變類(immutable class)。程序員
JDK中String的源碼數據庫
public final class String implements Serializable, Comparable<String>, CharSequence { /** The value is used for character storage. */ private final char[] value; /** Cache the hash code for the string */ private int hash;// Default to 0
能夠看到String的本質是一個char數組,是對字符串數組的封裝,而且是被final修飾的,建立後不可改變。數組
在Java中,因爲會大量的使用String常量,若是每一次聲明一個String都建立一個String對象,那將會形成極大的空間資源的浪費。Java提出了String pool的概念,在堆中開闢一塊存儲空間String pool,當初始化一個String變量時,若是該字符串已經存在了,就不會去建立一個新的字符串變量,而是會返回已經存在了的字符串的引用。緩存
String a = "Hello world!";
String b = "Hello world!";
若是字符串是可變的,某一個字符串變量改變了其值,那麼其指向的變量的值也會改變,String pool將不可以實現!安全
看下面這個場景,一個函數appendStr()在不可變的String參數後面加上一段「bbb」後返回。appendSb()負責在可變的StringBuilder後面加"bbb"。網絡
public class test { // 不可變的String public static String appendStr(String s) { s += "bbb"; return s; } // 可變的StringBuilder public static StringBuilder appendSb(StringBuilder sb) { return sb.append("bbb"); } public static void main(String[] args) { String s = new String("aaa"); String ns = test.appendStr(s); System.out.println("String aaa>>>" + s.toString()); // StringBuilder作參數 StringBuilder sb = new StringBuilder("aaa"); StringBuilder nsb = test.appendSb(sb); System.out.println("StringBuilder aaa >>>" + sb.toString()); } }
若是程序員不當心像上面例子裏,直接在傳進來的參數上加上「bbb」.由於Java對象參數傳的是引用,全部可變的StringBuffer參數就被改變了。能夠看到變量sb在Test.appendSb(sb)操做以後,就變成了"aaabbb"。
有的時候這可能不是程序員的本意。因此String不可變的安全性就體如今這裏。多線程
在併發場景下,多個線程同時讀一個資源,是安全的,不會引起競爭,但對資源進行寫操做時是不安全的,不可變對象不能被寫,因此保證了多線程的安全。併發
The advantage of immutability comes with concurrency. It is difficult to maintain correctness in mutable objects, as multiple threads could be trying to change the state of the same object, leading to some threads seeing a different state of the same object, depending on the timing of the reads and writes to the said object.
By having an immutable object, one can ensure that all threads that are looking at the object will be seeing the same state, as the state of an immutable object will not change.app
在網絡鏈接和數據庫鏈接中字符串經常做爲參數,例如,網絡鏈接地址URL,文件路徑path,反射機制所須要的String參數。其不可變性能夠保證鏈接的安全性。若是字符串是可變的,黑客就有可能改變字符串指向對象的值,那麼會引發很嚴重的安全問題。
由於String是不可變的,因此它的值是不可改變的。但因爲String不可變,也就沒有任何方式能修改字符串的值,每一次修改都將產生新的字符串,若是使用char[]來保存密碼,仍然可以將其中全部的元素設置爲空和清零,也不會被放入字符串緩存池中,用字符串數組來保存密碼會更好。
因爲String是不可變的,保證了hashcode的惟一性,因而在建立對象時其hashcode就能夠放心的緩存了,不須要從新計算。這也就是Map喜歡將String做爲Key的緣由,處理速度要快過其它的鍵對象。因此HashMap中的鍵每每都使用String。
在String類的定義中有以下代碼:
private int hash;//用來緩存HashCode
整體來講,String不可變的緣由要包括 設計考慮,效率優化,以及安全性這三大方面。
https://blog.csdn.net/jiahao1186/article/details/81150912
https://blog.csdn.net/u012546526/article/details/44458185
https://blog.csdn.net/hyddhy/article/details/87105691
https://www.cnblogs.com/wcyBlog/p/4073725.html、