學習 Java 的數據類型時,特殊關照了 String 類型,具備不變性。安全
當時沒有深刻思考爲何 String 有不變性。並且我只碰到了 String 纔有不變性。Java這樣設計的原因何在。網絡
忽然在想,爲何 Struts2 中的 action 的返回值爲何也是 String 類型的,不是其餘類型,SpringMVC中 handle 也是返回的是 String 類型【ModelAndView 裏面也包含了視圖名的字符串形式,void就不提了,處理 AJAX 】。框架
下面就好好分析這個字符串不變性。學習
所謂不變性就是一旦建立一個字符串對象,這個字符串對象的內容就不會被改變了。好比:ui
package com.msym.test; public class Test { public void show() { String str1 = "aaa"; String str2 = "aaa"; String str3 = new String("aaa"); System.out.println("str1的hashCode: " + str1.hashCode()); System.out.println("str2的hashCode: " + str2.hashCode()); System.out.println("str3的hashCode: " + str3.hashCode()); str1 = "aaa" + "b"; System.out.println("str1的hashCode: " + str1.hashCode()); System.out.println("str2的hashCode: " + str2.hashCode()); } @org.junit.Test public void test(){ show(); } }打印出來的結果說明,str1,str2,str3是指向同一塊內存空間的,當修改了 str1時,就建立了一個新的字符串了。spa
上面建立 str1,str2,str3:線程
建立 str1 時,常量池裏面確定是沒有常量「aaa」,因此會建立出一個,可是當建立 str2時,由於以前已經建立過 「aaa」了,因此會直接指向這個「aaa」;建立 str3 時,儘管使用了 new 關鍵字,可是仍是會先去常量池去搜尋「aaa」,若是存在,就只在堆內存中開闢一段空間,用以存放常量池中「aaa」的地址,若是不存在,那麼就先在常量池中建立「aaa」,而後在堆中開闢空間,存儲常量池中「aaa」的地址。設計
下面畫張圖來講明:【其中的 0X1122 是常量池中「aaa」的地址頭,】code
並且 String 類的任何方法都不是去修改字符串的值,而是建立了一個新的字符串,原來的字符串若是沒有被引用的話,會在一段時間內被 gc 掉,這樣貌似看來,這個不變性並無帶來什麼好處,反倒浪費了很多內存,可是這樣的機制正好有了安全性,只要建立出一個 String 對象,只要他沒有被 gc ,任何方法來讀取這個對象都會是同一個,不會出現兩個同樣的,這也是爲何 String 類型在網絡鏈接,數據傳遞,以及各大框架使用的這麼頻繁。對象
固然,若是隻是想使用 String類的功能,有更好的選擇,那就是線程安全的 StringBuffer和線程不安全的StringBuilder。
1