String底層原理
今天模擬面試遇到一位同學,剛好問到一個問題
我問他 String的底層原理是什麼
他思考了一會說不知道。
那麼我們在面試的時候有可能會遇到類似的問題,怎麼去解答,肯定是要去看String的原始碼的
public final class String implements java.io.Serializable, Comparable<String>, CharSequence { private final char value[]; private int hash; // Default to 0 private static final long serialVersionUID = -6849794470754667710L; ......此處省略N多程式碼 /** * Initializes a newly created {@code String} object so that it represents * the same sequence of characters as the argument; in other words, the * newly created string is a copy of the argument string. Unless an * explicit copy of {@code original} is needed, use of this constructor is * unnecessary since Strings are immutable. * * @param original * A {@code String} */ public String(String original) { this.value = original.value; this.hash = original.hash; } }
在上面 貼出了String的原始碼,我們可以看到,String類是final修飾的,然後還有個成員屬性 value 它也是final的並且是一個char型別的陣列
通過構造方法可以看到,我們傳遞的引數值 是直接賦值給了 value
那麼我們說明 String它是一個不可變字串,底層是一個char型別的陣列
實際上我們經常 這樣寫 String a = "abc"; 這個時候 宣告的變數值是在常量池中的。
到此,有的同學可能要說了,String裡面我們不是可以使用 + 連線符 來進行String的拼接嗎。
的確如此,我們是可以使用 "+" 來拼接字串,不過 這裡 jdk的虛擬機器是做了優化的,並不是表面看到的使用 連線符 對原來的String做了拼接,那麼我們來看下 它是如何編譯的。
有如下程式碼:
public class Test{
public static void main(String [] args){
String str = "abc";
String str1= "def";
str = str+str1;
System.out.println(str);
}
}
我們在控制檯 中 通過 javac 編譯,然後通過java執行 看到結果是
結果都知道是 "abcdef" 那麼這個地方的str到底是否被改變,我們可以看編譯後的class位元組碼檔案
我們通過 javap -c Test 來觀察,結果如下圖
我們看到Code 的 第 0 和 第 3 標識處,是我們宣告的變數值 "abc" 和 "def"
再往下走,我們在java中的程式碼是使用了 "+" 連線符號的,此處看到 Code 第 6 處 new StringBuilder
再往下走,看到 Code 的第 14 和 第 18 ,使用了StringBuilder的 append(),那麼我們可以得出一個結論,我們在使用String的時候,使用連線符,並不是表面看到的是直接操作原來的變數做值的拼接,而是使用的StringBuilder物件,追加的內容,
最後 在 Code的21處,有一個 toString()方法,是把當前StringBuilder的物件變成了String。
好了,到此,我們剖析String原始碼到此結束。
結論就是 String底層是一個不可變字串,使用連線符的時候,實際上是經過了StringBuilder的優化處理的。並不是在原來的String物件中做追加