String、StringBuffer和StringBuilder的區別和實現原理
String
String是java中用的最頻繁的類之一,其內部原理是通過char[]數組實現的。其實內部char[]是定義的常量 .
private final char value[];
public String() {
this.value = "".value;
}//默認是"";
public String(String original) {
this.value = original.value;
this.hash = original.hash;
}
一旦定義之後不可改變,能夠改變的String變量的引用地址。比如String b=new String ();指向String 創建的在堆中的對象地址,b= new String("ssss");這樣b再次指向另一個在堆中的某一對象地址。而之前堆中的String對象的value是常量並沒有發生改變
簡而言之創建的String變量可以重新指向對象但是String的一個對象中的value數組是不能改變的這也就是爲什麼定義的對象無法進行末尾追加值的原因(因爲你想要改變String的長度需要操作value對象而value對象唄關鍵字final修飾了)。
注意
1 當使用任何方式來創建一個字符串對象s時,Java運行時(運行中JVM)會拿着這個X在String池中找是否存在內容相同的字符串對象,如果不存在,則在池中創建一個字符串s,否則,不在池中添加。
2 Java中,只要使用new關鍵字來創建對象,則一定會(在堆區或棧區)創建一個新的對象。
3 使用直接指定或者使用純字符串串聯來創建String對象,則僅僅會檢查維護String池中的字符串,池中沒有就在池中創建一個,有則罷了!但絕不會在堆棧區再去創建該String對象。
4 使用包含變量的表達式來創建String對象,則不僅會檢查維護String池,而且還會在堆棧區創建一個String對象。
另外,String的intern()方法是一個本地方法,定義爲public native String intern(); intern()方法的價值在於讓開發者能將注意力集中到String池上。當調用 intern 方法時,如果池已經包含一個等於此 String 對象的字符串(該對象由 equals(Object) 方法確定),則返回池中的字符串。否則,將此 String 對象添加到池中,並且返回此 String 對象的引用。
StringBuilder
StringBuffer類是線程安全的,他的方法都是synchronized關鍵字修飾的
StringBuilder類是線程不安全的
StringBuilder是可變長度的字符串長度類但是不是線程安全的而Stringbuffer 是線程安全的這是他們兩者的區別(線程安全速度就慢),(詳見看線程安全詳解)StringBuilder也是用char[]構成的但是他可以改變對象的長度。因爲內部並沒有使用final關鍵字,在StringBuilder的append方法中對對象value值進行修改。
線程安全性
這三個類在進行操作時的速度關係爲:StringBuilder > StringBuffer > String
由於String中進行操作時都會新建一個char[ ]數組代替原來的char[ ]數組,所以速度最慢
StringBuffer線程安全,每個方法都有synchronized同步阻塞,所以操作速度受影響
StringBuilder沒有同步阻塞的限制,所以操作速度最快
使用場景
-
如果要操作少量的數據用 = String
-
單線程操作字符串緩衝區 下操作大量數據 = StringBuilder
-
多線程操作字符串緩衝區 下操作大量數據 = StringBuffer
常用方法、
String都比較熟悉,這裏只整理StirngBuffer/StringBuilder類的方法,這兩個類大多數方法都是繼承於AbstractStringBuilder父類
1、append(String str) 追加內容到當前StirngBuffer/StringBuilder對象的末尾,類似於字符串的連接
2、deleteCharAt(int k)刪除指定位置的字符,然後將剩餘的內容形成新的字符串
3、delete(int start, int end) 刪除指定區間以內的所有字符,包含start,不包含end索引的區間
4、insert(int index, String str) 在StirngBuffer/StringBuilder對象指定位置中插入內容str,然後形成新的字符串
5、reverse() 將StirngBuffer/StringBuilde對象中的內容反轉,然後形成新的字符串
==與equals的區別
==指的是指向對象的地址是否相同。equal內部方法是把char[]的每一個值進行對比相同就返回true有一個不同就返回false。
例子:
String s1=new String("s");
String s2=new String("s");
System.out.println(s1==s2);
System.out.printlc(s1.equals(s2));
最後運行結果爲false true;因爲new出來對象地址不同所以不相同,而值是一樣的故而得到的是false和true
String s1="s";
String s2="s";
System.out.println(s1==s2);
System.out.println(s1.equals(s2));
最後運行結果爲true true這是
因爲它們都是從緩衝池取出來的,由於string類比較特殊,jdk專門做了緩存優化。
Java運行時會維護一個String Pool(String池)。String池用來存放運行時中產生的各種字符串,並且池中的字符串的內容不重複。而一般對象不存在這個緩衝池,並且創建的對象僅僅存在於方法的堆棧區。
也就是說需要看string創建的方式:
參考博客
https://blog.csdn.net/Orient_/article/details/89343115