1. 程式人生 > 其它 >Java常用類--String(一)Stirng的儲存

Java常用類--String(一)Stirng的儲存

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[] 的值。