天天看點

String字元串的一些了解例子:列印結果:分析:

例子:

String str1 = "a" + "b" + "c";  //記憶體位址1(常量池:編譯時已轉換為"abc")
String str2 = "abc";            //記憶體位址1(常量池)
String str3 = "ab";//(常量池)
final String str4 = "ab"; //(常量池)
String str5 = str3 + "c";       //記憶體位址3(堆記憶體:由于編譯的時候不能确定str3的值,是以利用StringBuffer拼接字元串)
String str6 = str4 + "c";       //記憶體位址1(常量池:由于str4用final定義,則不可以修改,是以編譯時直接拼接為"abc")
String str7 = new String("abc");    //記憶體位址4(堆記憶體)
String str8 = new String(str2);            //記憶體位址5(堆記憶體)

Log.i(TAG, "str1 == str2  " + (str1 == str2)); //true
Log.i(TAG, "str1.equals(str2)  " + str1.equals(str2) + "\n"); //true

Log.i(TAG, "str1 == str5  " + (str1 == str5)); //false
Log.i(TAG, "str1.equals(str5)  " + str1.equals(str5) + "\n"); //true
Log.i(TAG, "str1 == str6  " + (str1 == str6)); //true
Log.i(TAG, "str1.equals(str6)  " + str1.equals(str6) + "\n"); //true

Log.i(TAG, "str1 == str7  " + (str1 == str7)); //false
Log.i(TAG, "str1.equals(str7)  " + str1.equals(str7) + "\n"); //true
Log.i(TAG, "str1 == str8  " + (str1 == str8)); //false
Log.i(TAG, "str1.equals(str8)  " + str1.equals(str8) + "\n"); //true
Log.i(TAG, "str7 == str8  " + (str7 == str8)); //false
Log.i(TAG, "str7.equals(str8)  " + str7.equals(str8) + "\n"); //true      

列印結果:

05-30 17:48:44.051 3057-3057/ str1 == str2  true
05-30 17:48:44.051 3057-3057/ str1.equals(str2)  true
05-30 17:48:44.051 3057-3057/ str1 == str5  false
05-30 17:48:44.051 3057-3057/ str1.equals(str5)  true
05-30 17:48:44.051 3057-3057/ str1 == str6  true
05-30 17:48:44.051 3057-3057/ str1.equals(str6)  true
05-30 17:48:44.051 3057-3057/ str1 == str7  false
05-30 17:48:44.051 3057-3057/ str1.equals(str7)  true
05-30 17:48:44.051 3057-3057/ str1 == str8  false
05-30 17:48:44.051 3057-3057/ str1.equals(str8)  true
05-30 17:48:44.051 3057-3057/ str7 == str8  false
05-30 17:48:44.051 3057-3057/ str7.equals(str8)  true      

分析:

個人了解:

常量池:常量存放區域,友善對象重複利用。

棧:定義的屬性存放區域

堆:new出來的對象存放的區域

方法區:存放靜态變量,靜态代碼塊等

1.str1分析:

String str1 = "a" + "b" + "c";      

"a" + "b" + "c"在編譯的時候,會被編譯器優化為"abc",存在于常量池。

記憶體關系:棧記憶體的變量str1的指針指向于常量池的字元串"abc"。

2.str2分析:

String str2 = "abc";      

"abc",存在于常量池,str2存在于棧記憶體

記憶體關系:棧記憶體的變量str2的指針指向于常量池的字元串"abc"。

3.str5分析:

String str3 = "ab";

String str5 = str3 + "c";      

由于str3是一個變量,是以在編譯期間jvm,并不能将直接轉換為字元串"abc",而是首先建立一個StringBuilder類,再

用StringBuilder類的append方法将str3和字元串"c"拼接,最後通過StringBuilder的toString()方法傳回一個

String指派給str5,因為字元串"abc"是new出來的是以存在于堆記憶體。

記憶體關系:棧記憶體的變量str5的指針指向于堆記憶體的String對象,堆記憶體的String對象指針指向于常量池的字元串對象"abc"。

4.str6分析:

final String str4 = "ab";

String str6 = str4 + "c";      

由于變量str4被final修飾,意味着不能修改,是以編譯器在編譯階段就會将str4 + "c"簡化為字元串"abc",]存在于常

量池。

記憶體關系:棧記憶體變量str6的指針指向常量池的字元串"abc"。

5.str7分析:

String str7 = new String("abc");      

首先編譯器會在常量池當中尋找是否有字元串"abc",假如沒有,則會在常量池當中建立字元串"abc",new String("abc")

調用了String類的參數為String的構造方法,這個方法最主要做的事情就是建立一個String對象,并且将"abc"的值淺拷貝

一份給String對象,接着将String對象指派給str7。

記憶體關系:棧記憶體變量str7的指針指向堆記憶體的String對象,堆記憶體的String對象指向常量池的"abc"對象。

6.str8分析:

String str2 = "abc";            //記憶體位址1(常量池)

String str8 = new String(str2);      

由于String str2 = "abc";在前面已經确認了字元串"abc"已經在常量池建立了,是以當代碼運作到String = str8這句代

碼的時候,會建立一個String對象,并且String對象的指針指向于常量池的字元串"abc"。

記憶體關系:棧記憶體變量str8的指針指向堆記憶體的String對象,對記憶體的String對象指向于常量池的"abc"對象。

由以上分析可知:str1的記憶體位址 == str2的記憶體位址 == str6的記憶體位址。

str1 != str5 != str7 != str8

str5,str7,str8的記憶體位址各不同。但是str1,str2,str6,str7,str8的值的記憶體位址一緻都是為常量池當中的"abc",

隻有str5的值的記憶體位址在堆記憶體 。

注:如有不對,請指出,謝謝。