Java常用類--String(一)Stirng的儲存
阿新 • • 發佈:2021-07-17
String類的特性
- 1.String宣告為final的,不可被繼承
- 2.String實現了Serializable介面:表示字串是支援序列化的。
- 實現了Comparable介面:表示String可以比較大小
- 3.String內部定義了final char[] value用於儲存字串資料
- 4.String:代表不可變的字元序列。簡稱:不可變性。
體現:
-
- 1.當對字串重新賦值時,需要重寫指定記憶體區域賦值,不能使用原有的value進行賦值。
- 2. 當對現有的字串進行連線操作時,也需要重新指定記憶體區域賦值,不能使用原有的value進行賦值。
- 3. 當呼叫String的replace()方法修改指定字元或字串時,也需要重新指定記憶體區域賦值,不能使用原有的value進行賦值。
即方法區中不能含有兩個值相同的地址空間,原S1 = S2時兩個變數指向的地址是相同的,當s1的值改變時,方法區中重新劃出一塊地址空間並重新賦值,s1指向新的地址空間。
1 @Test 2 public void test1(){ 3 String s1 = "abc";//字面量的定義方式 4 String s2 = "abc"; 5 s1 = "hello"; 6 7 System.out.println(s1 == s2);//比較s1和s2的地址值 8 9 System.out.println(s1);//hello 10 System.out.println(s2);//abc 11 12 System.out.println("*****************"); 13 14 String s3 = "abc"; 15 s3 += "def"; 16 System.out.println(s3);//abcdef 17 System.out.println(s2); 18 19 System.out.println("*****************"); 20 21 String s4 = "abc";22 String s5 = s4.replace('a', 'm'); 23 System.out.println(s4);//abc 24 System.out.println(s5);//mbc 25 26 }
- 5.通過字面量的方式(區別於new)給一個字串賦值,此時的字串值宣告在字串常量池中。
- 6.字串常量池中是不會儲存相同內容的字串的。
String物件的建立
方式一:通過字面量定義的方式
方式二:通過new + 構造器的方式
1 @Test 2 public void test2(){ 3 //通過字面量定義的方式:此時的s1和s2的資料javaEE宣告在方法區中的字串常量池中。 4 String s1 = "javaEE"; 5 String s2 = "javaEE"; 6 //通過new + 構造器的方式:此時的s3和s4儲存的地址值,是資料在堆空間中開闢空間以後對應的地址值。 7 String s3 = new String("javaEE"); 8 String s4 = new String("javaEE"); 9 10 System.out.println(s1 == s2);//true 11 System.out.println(s1 == s3);//false 12 System.out.println(s1 == s4);//false 13 System.out.println(s3 == s4);//false 14 15 System.out.println("***********************"); 16 Person p1 = new Person("Tom",12); 17 Person p2 = new Person("Tom",12); 18 19 System.out.println(p1.name.equals(p2.name));//true 20 System.out.println(p1.name == p2.name);//true 21 22 p1.name = "Jerry"; 23 System.out.println(p2.name);//Tom 24 }
結論:
1.常量與常量的拼接結果在常量池。且常量池中不會存在相同內容的常量。
2.只要其中有一個是變數,結果就在堆中。
3.如果拼接的結果呼叫intern()方法,返回值就在常量池中
1 @Test 2 public void test4(){ 3 String s1 = "javaEEhadoop"; 4 String s2 = "javaEE"; 5 String s3 = s2 + "hadoop"; 6 System.out.println(s1 == s3);//false 7 8 final String s4 = "javaEE";//s4:常量 9 String s5 = s4 + "hadoop"; 10 System.out.println(s1 == s5);//true 11 12 } 13 14 @Test 15 public void test3(){ 16 String s1 = "javaEE"; 17 String s2 = "hadoop"; 18 19 String s3 = "javaEEhadoop"; 20 String s4 = "javaEE" + "hadoop"; 21 String s5 = s1 + "hadoop"; 22 String s6 = "javaEE" + s2; 23 String s7 = s1 + s2; 24 25 System.out.println(s3 == s4);//true 26 System.out.println(s3 == s5);//false 27 System.out.println(s3 == s6);//false 28 System.out.println(s3 == s7);//false 29 System.out.println(s5 == s6);//false 30 System.out.println(s5 == s7);//false 31 System.out.println(s6 == s7);//false 32 33 String s8 = s6.intern();//返回值得到的s8使用的常量值中已經存在的“javaEEhadoop” 34 System.out.println(s3 == s8);//true 35 36 37 }
問:String s = new String("abc");方式建立物件,在記憶體中建立了幾個物件?
答:兩個;一個是堆空間中new結構,另一個是char[]對應的常量池中的資料:"abc"
一道面試題:
1 public class StringTest { 2 3 String str = new String("good"); 4 char[] ch = { 't', 'e', 's', 't' }; 5 6 public void change(String str, char ch[]) { 7 str = "test ok"; 8 ch[0] = 'b'; 9 } 10 public static void main(String[] args) { 11 StringTest ex = new StringTest(); 12 ex.change(ex.str, ex.ch); 13 System.out.println(ex.str);//good 14 System.out.println(ex.ch);//best 15 } 16 }
因為基本資料型別傳入的是資料,引用資料型別傳入的是地址值。由於String是不可變型,呼叫change方法時,str和傳入的str指向同一個地址,但是方法體中的str改變了,產生了一個新的地址,但是原str指向的地址中的值並沒有變。所以str依然是good,方法體中的str為 test ok,此時的str只是一個區域性變數,如果在方法體中用sout輸出str則會輸出test ok。
又因為char[]雖然也是引用資料型別,但並沒有不可變型,所以可以在方法體中直接對陣列進行操作,所以可以改變char[] 的值。