半夜思考,爲何 String 具備不變性

學習 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();
    }
}

image

打印出來的結果說明,str1,str2,str3是指向同一塊內存空間的,當修改了 str1時,就建立了一個新的字符串了。spa

上面建立 str1,str2,str3:線程

        建立 str1 時,常量池裏面確定是沒有常量「aaa」,因此會建立出一個,可是當建立 str2時,由於以前已經建立過  「aaa」了,因此會直接指向這個「aaa」;建立 str3 時,儘管使用了 new 關鍵字,可是仍是會先去常量池去搜尋「aaa」,若是存在,就只在堆內存中開闢一段空間,用以存放常量池中「aaa」的地址,若是不存在,那麼就先在常量池中建立「aaa」,而後在堆中開闢空間,存儲常量池中「aaa」的地址。設計

下面畫張圖來講明:【其中的 0X1122 是常量池中「aaa」的地址頭,】code

image

      並且 String 類的任何方法都不是去修改字符串的值,而是建立了一個新的字符串,原來的字符串若是沒有被引用的話,會在一段時間內被 gc 掉,這樣貌似看來,這個不變性並無帶來什麼好處,反倒浪費了很多內存,可是這樣的機制正好有了安全性,只要建立出一個 String 對象,只要他沒有被 gc ,任何方法來讀取這個對象都會是同一個,不會出現兩個同樣的,這也是爲何 String 類型在網絡鏈接,數據傳遞,以及各大框架使用的這麼頻繁。對象

 

固然,若是隻是想使用 String類的功能,有更好的選擇,那就是線程安全的 StringBuffer和線程不安全的StringBuilder。

 

 

 

 

 

 

 

 

 

 

 

1

相關文章
相關標籤/搜索