在Java程序中經常會遇到類似於"Hello"這樣地字符串,那么這種類型的字符串是Java中是如何存儲,下面就來討論一下字符串常量在內存中的存儲方式
Java程序在編譯時會將程序中出現的常量(包括:char、byte、short、int、long、boolean和String類型)放到一個叫做常量池的地方。常量池也稱為對象池,顧名思義 常量池中存儲的是對象。
那么在源程序中檢測到"Hello"這樣地常量字符串之后,編譯器都干了些什么:
首先,在常量池中創建一個String對象,該對象的內存分布如下圖:
這里就需要提一下String定義的兩個變量:
private final char value[]; //The value is used for character storage
private int hash; //Cache the hash code for the string
其中第一個就是實際存儲字符串的數組,所有字符串最終的存儲形式都是字符數組。從上圖中可以很清晰的看出,實際的字符數組還是存儲在堆中,常量池中存儲的是String對象。
當執行String str = "Hello",只是將常量池中"Hello"對象的地址賦給了str。
除了上面這個字符串常量的內存模型需要理清之外,String類還有幾個很常用的構造函數,也需要對內存模型非常熟悉:
1. public String() {
this.value = "".value;
}
這是默認的構造函數,它將一個空串的字符數組引用賦給了本類的數組數組引用,所以這個String對象中什么也沒有當然這樣做並沒有什么好處,因為String對象一但創建便不可更改其內容(從value的修飾關鍵字final可以看出)。
2. public String(String original) {
this.value = original.value;
this.hash = original.value;
}
這里只是簡單的復制了引用的值,並沒有復制引用的內容,它們仍然指向同一個對象。
3. public String(char value[]) {
this.value = Arrays.copyOf(value, value.length);
}。
Array.copyOf()會將value中的值重新拷貝一份出來,所以this.value和參數中的value完全是兩個對象,只不過它們的值相同而已
其余的構造函數也基本類似,大家可自行分析