Java之String/StringBuffer/StringBuilder
阿新 • • 發佈:2020-09-18
目錄
三者關係
https://blog.csdn.net/jisuanjiguoba/article/details/82531868
https://www.runoob.com/w3cnote/java-different-of-string-stringbuffer-stringbuilder.html
https://www.zhihu.com/question/20101840
- 快慢關係
StringBuilder>StringBuffer>String
為何String最慢呢?因為String是不可變的,所以要修改時(其實就是將String指向了一個新物件,內容是修改的字串值),涉及到建立和回收物件,所以耗時。具體解釋如下:
- 執行緒安全與否
String不可變,所以自然是執行緒安全
StringBuffer是執行緒安全,因為很多方法都由synchronized關鍵詞來修飾
StringBuilder不是執行緒安全的
- 三者相互轉換
- String vs. StringBuffer (StringBuilder轉換類似)
public class StringAndStringBufferSwitch { public static void main(String[] args) { //String -> StringBuffer //建立一個String物件 String str = "Hi Java!"; System.out.println(str); //方式一:構造方法 StringBuffer buffer = new StringBuffer(str); System.out.println(buffer); //方式二:通過append方法 StringBuffer buffer2 = new StringBuffer(); buffer2.append(str); System.out.println(buffer2); //StringBuffer -> String //建立一個StringBuffer物件 StringBuffer buffer3 = new StringBuffer(); buffer3.append("Happy birthday Java!"); System.out.println(buffer3); //方式一:通過構造方法 String str2 = new String(buffer3); System.out.println(str2); //方式二:通過toString方法 String str3 = buffer3.toString(); System.out.println(str3); } }
String
https://github.com/CyC2018/CS-Notes
https://blog.csdn.net/fly_fly_fly_pig/article/details/82492491
- 特性
不可變,final修飾。在java8中,String內部使用char陣列;在java9中,使用byte陣列
不可變的好處:適合作map的鍵值、天生支援多執行緒、比較安全(比如傳送網路地址時)、String pool的需要 - 關於String的="xxx"和new String("xxx")區別,以及字串相等的判定,以及intern()函式的使用,見下面的程式碼解釋:
public class TestString {
public static void main(String[] args) {
//直接使用="xxx"構造,會自動將“xxx”放入String pool,因此s2構造時,直接指向s1當時構造的“abc”。因此兩者hashcode或==都一樣
String s1 = "abc";
String s2 = "abc";
System.out.println(s1.equals(s2));
System.out.println("s1.hashcode: "+s1.hashCode()+"; s2.hashcode: "+s2.hashCode());
System.out.println(s1 == s2);
//此時String pool中已有“abc”,因此雖然是使用new String("abc")新建一個物件,但是查詢到String pool已有,同樣也是指向相同的引用
String s3 = new String("abc");
System.out.println("s3.hashcode: "+s3.hashCode());
//然而,若我們用new String新建兩個相同的字串但是之前未出現在String pool中,則兩者的引用不同
String s4 = new String("xyz");
String s5 = new String("xyz");
System.out.println(s4.equals(s5)); //true,因為值相等
System.out.println("s4.hashcode: "+s4.hashCode()+"; s5.hashcode: "+s5.hashCode());
System.out.println(s4 == s5); //不同,因為是兩個不同的物件,雖然指向的是同一個地址
//所以要注意,hashcode相同,也不一定就是同一個物件~
//使用intern()可手動將字串放入String pool,這樣的話==就為true
String s6 = s4.intern();
String s7 = s4.intern();
System.out.println(s6.equals(s7));
System.out.println("s6.hashcode: "+s6.hashCode()+"; s7.hashcode: "+s7.hashCode());
System.out.println(s6 == s7);
//若使用一個物件作為新new物件的建構函式的引數時,value和hash都相同,但是s7,s8還是不同的物件。。
String s8 = new String(s7);
System.out.println(s7.equals(s8));
System.out.println("s7.hashcode: "+s7.hashCode()+"; s8.hashcode: "+s8.hashCode());
System.out.println(s7 == s8);
}
}
result:
true
s1.hashcode: 96354; s2.hashcode: 96354
true
s3.hashcode: 96354
true
s4.hashcode: 119193; s5.hashcode: 119193
false
true
s6.hashcode: 119193; s7.hashcode: 119193
true
true
s7.hashcode: 119193; s8.hashcode: 119193
false
注意:在 Java 7 之前,String Pool 被放在執行時常量池中,它屬於永久代。而在 Java 7,String Pool 被移到堆中。這是因為永久代的空間有限,在大量使用字串的場景下會導致 OutOfMemoryError 錯誤。
- 關於new String("xxx")後的操作
會生成兩個物件,一個是在String pool中生成指向“xxx”的字串物件,一個是new之後在堆上生成的字串物件 - String類方法
https://www.runoob.com/java/java-string.html
StringBuffer
https://www.runoob.com/java/java-stringbuffer.html
- 特殊方法:
public class TestStringBuffer {
public static void main(String[] args) {
StringBuffer s1 = new StringBuffer("abc");
System.out.println(s1);
s1.append("def");
System.out.println(s1);
s1.reverse();
System.out.println(s1);
s1.delete(1,2); //刪除下標為[1,2)的字元
System.out.println(s1);
s1.insert(1,1); //(int offset, int i),將int型的i插入到字串offset位置,其他字元後移
System.out.println(s1);
s1.replace(1,4,"kkk"); //用“kkk”替換掉下標為[1,4)的字元
System.out.println(s1);
}
}
result:
abc
abcdef
fedcba
fdcba
f1dcba
fkkkba
- 與String同樣的方法見https://www.runoob.com/java/java-stringbuffer.html
StringBuilder
StringBuffer 與 StringBuilder 中的方法和功能完全是等價的
https://www.cnblogs.com/onetheway2018/p/11553168.html