String類代筆的是字符串,是引用數據類型,Java中的全部字符串文字均可以被當作是這個類的實現數組
字符串表面上看起來存儲的是一個字符數組,可是其底層實際上存儲的是字符數組對應的字節數組。jvm
1 //初始化一個新建立的 String 對象,使其表示一個空字符序列。 2 public String(); 3 String string1 = new String(); 4 string1 = "abc"; 5 6 // 分配一個新的 String,使其表示字符數組參數中當前包含的字符序列。 7 public String(char[] chars); 8 char[] ch = {'a','b','c'}; 9 String string2 = new String(ch); 10 11 //經過使用平臺的默認字符集解碼指定的 byte 數組,構造一個新的 String。 12 public String( byte[] value); 13 byte[] b = {97, 98, 99}; 14 String string3 = new String(b); 15 16 //直接建立 17 String string4 = "abc";
下面我們來講一說這四種建立方式,優化
前三種建立方式是引用類型常見的建立方式,都是先在棧中定義一個String類型的變量,而後在堆中new一塊空間出來,把這塊空間的地址賦給棧中的變量spa
可是String類既然是引用數據類型,那爲何能夠不用new就能夠直接建立呢?3d
在聊這個以前就不得不說一下Java虛擬機(jvm)的底層劃分了,code
Java虛擬機分爲五個部分,分別是棧,堆、方法區、,用一張圖片說明一下,沒啥美術天分,畫的比較醜視頻
接着上個問題,爲何string能夠像基本數據類型那樣直接賦值?對象
在jvm的堆內存中有一塊東西叫作字符串常量池,在賦值的時候把裏面的一個地址賦給了string ,常量池中的的這個地址又指向的是堆中的一個字節數組,根據ASCII碼錶可知其實這樣就至關於存儲了對應的字符blog
1 String str1 = "abc"; 2 3 String str2 = "abc"; 4 5 String str3 = "a"; 6 7 String str4 = "bc"; 8 9 char[] ch = {'a','b','c'}; 10 11 String str5 = new String(ch);
上面的代碼中,來作個比較,(引用類型比較值是經過重寫Object類型的equals方法實現的,String類重寫過這份方法)圖片
str1 == str2結果居然是神奇的true,你們都知道字符串是引用類型,引用類型是不能直接進行比較的,直接比較結果相等意味着兩者的地址值相等,這也就是說他們兩個存儲的是同一個地址,爲何呢?這就是前面說過的字符串常量池的緣由了,若是給字符串直接賦值,它默認是調用字符串常量池裏的內容的因此兩者的地址其實都是指向了字符串常量池中的。
str1 == "a" + "bc";結果也是true,其實我們的JVM是很智能的,在編譯的時候虛擬機給咱們的代碼作了優化,其實就和第一種狀況是同樣的
str1 == str3 + "bc"; 這時候結果就出現變化了,由於整個出現了變量,在編譯的時候虛擬機遇到變量就不會幫你把表達式轉換成第一種狀況了。
str1 == str4 這個結果其實你們已經能夠想到了,結果是false,由於兩者的地址是徹底不同的。
語言表達能力實在有限,放一張圖把,圖片來源黑馬的培訓視頻。
寫文章的目的是爲了讓本身之後查找起來更加便捷一點,可能會右不少錯誤,之後慢慢再來更正。