文章目錄
java基礎學習(1)-String相關知識
1.String、StringBuffer與StringBuilder的區別
- 可變性
String不可變
StringBuffer和StringBuilder可變 - 線程安全
String不可變,因此爲線程安全
StringBuilder是線程不安全的
StringBuffer是線程安全的,內部使用synchronized同步
2.String不可變的好處
1.可以緩存hash值
因爲String的hash值經常被使用,例如String作爲HashMap的key。不變性可以使hash之不會發生變化,因此只需要進行一次計算。
2.String Pool的需要
如果一個String對象已經被創建了,那麼再次生成或者使用需要從String Pool中獲取引用。只有String是不可變的,纔可能是使用String Pool。
3.安全性
String經常作爲參數,String的不變性保證了參數的不可變。例如在作爲網絡連接參數的情況下如果String可變,那麼在網絡連接的過程中,String改變,改變String的那一方以爲現在連接的是其他主機,而實際情況卻不一定是。
4.線程安全
String 不可變性天生具備線程安全,可以在多個線程中安全地使用。
3.String底層數據結構變化
String 被聲明爲 final,因此它不可被繼承。
底層數組被聲明爲 final,這意味着 value 數組初始化之後就不能再引用其它數組。並且 String 內部沒有改變 value 數組的方法,因此可以保證 String 不可變。
在 Java 8 中,String 內部使用 char 數組存儲數據。
在 Java 9 之後,String 類的實現改用 byte 數組存儲字符串,同時使用 coder 來標識使用了哪種編碼。
4.String Pool
字符串常量池(String Pool)保存着所有字符串字面量(literal strings),這些字面量在編譯時期就確定。不僅如此,還可以使用 String 的 intern() 方法在運行過程將字符串添加到 String Pool 中。
當一個字符串調用 intern() 方法時,如果 String Pool 中已經存在一個字符串和該字符串值相等(使用 equals() 方法進行確定),那麼就會返回 String Pool 中字符串的引用;否則,就會在 String Pool 中添加一個新的字符串,並返回這個新字符串的引用。
下面示例中,s1 和 s2 採用 new String() 的方式新建了兩個不同字符串,而 s3 和 s4 是通過 s1.intern() 方法取得同一個字符串引用。intern() 首先把 s1 引用的字符串放到 String Pool 中,然後返回這個字符串引用。因此 s3 和 s4 引用的是同一個字符串。
String s1 = new String("aaa");
String s2 = new String("aaa");
System.out.println(s1 == s2); // false
String s3 = s1.intern();
String s4 = s1.intern();
System.out.println(s3 == s4); // true
如果是採用 “bbb” 這種字面量的形式創建字符串,會自動地將字符串放入 String Pool 中。
String s5 = "bbb";
String s6 = "bbb";
System.out.println(s5 == s6); // true
在 Java 7 之前,String Pool 被放在運行時常量池中,它屬於永久代。而在 Java 7,String Pool 被移到堆中。這是因爲永久代的空間有限,在大量使用字符串的場景下會導致 OutOfMemoryError 錯誤。