標籤:java基礎疑難解答
首先要明白,java只用的wrapper類型都是不可變的,什麼是不可變類型呢?顧名思義,就是這種類型的對象一旦建立好之後,無論調用何種方法都無法改變該對象的任何的屬性。String 源碼中,它的所有屬性都是private final的,因此,只有在構造string對象的時候,這些屬性才是可以修改的,string類的方法中需要返回一個string的,如subString,concat等方法,都會先構造一個新的string對象,然後再返回,而原來的string對象是不會發生改變的。
StringBuffer與數組的區別:
stringbuffer:長度可變,而數組的長度不可變。
StringBuffer 與 StringBuider :
StringBuffer 是synchronized,安全執行緒的,在多線程中使用。
StringBuider 是非安全執行緒的,在單線程中使用(比較普遍)。該類是作為StringBuffer 類的一個簡單的替換。
String類和StringBuider主要效能區別:
String: 每次對String類型對象改變時,都會產生一個新的String對象,然後將指標指向新的string對象,所以經常改變內容的字串最 好不要使用String。因為每次產生的對象都會對系統效能產生影響,特別當記憶體中無引用的對象多了以後,JVM的GC就開始工 作,系統的效能就會降低。
StringBuffer: 使用StringBuffer對象時,每次都會對對象本身進行操作,而不是產生新的對象並改變對象引用,所以多次情況下,尤 其在字串對象經常改變的情況下使用StringBuffer。
但是使用:String s1="this"+"is"+"a"+"simple"+"test";
比 StringBuffer sb=new StringBuffer("this is a ").append("simple").append("test");
快,因為在JavaCompiler中,會把第一個語句自動編譯為:String s1="this is a simple test";
但,拼接的字串來自另外的String對象的話,JavaCompiler就不會自動轉換了,速度也就慢了,比如下面這樣的。
String s2="this is a";
String s3="simple";
String s4="test";
String s1=s2+s3+s4;
這時候,Java compiler會股規矩矩的按照原來的方式去做。String的concatenation(即+)操作利用了StringBuffer(或StringBuider)的append方法實現,此時,對於上述情況,若,s2,s3,s4採用String定義,拼接時需要額外建立一個
StringBuffer(或StringBuider)之後將StringBuffer轉換為String;而且S1在運行時才能知道具體的值。若採用StringBuffer
則,不需要額外建立StringBuffer 。
使用原則:
1.如果操作少量資料,用String;單線程操作大量資料用StringBuider 。多線程大量資料用StringBuffer 。
2.不要使用String類的"+"操作,來頻繁拼接,因為那樣效能極差,應該使用StringBuffer 或者StringBuider。這在java的最佳化上 也是一條重要原則。
3.為了獲得更好的效能,在構造StringBuffer 或者StringBuider的時候應該盡量可能指定他們的容量。如果操作的字串長度 (length)不超過容量為16個字元的對象就不用了。超過的話,不指定容量會降低效能。
4.StringBuider一般使用在方法內部來完成類似"+"的功能。因為是線程不安全的,所以用完就可以丟棄。StringBuffer 主要用 在全域變數。
5.相同情況下,使用StringBuider相比使用StringBuffer 僅能獲得10%~·5%左右的效能提升,卻要冒著多線程不安全的風險。
非可變類(immutable)的真正唯一缺點:對於每一個不同的值都要求一個單獨的對象。
優點:容易設計,實現和使用,不易出錯,安全執行緒,在其生命週期內它的值永遠不變。
StringBuffer 充當了String的Companying class(配套累)
StringBuffer的常用方法:
StringBuffer append("data");//將指定的資料(各種資料)作為參數,添加到已有的資料結尾處
StringBuffer insert(index,"data");//可以將資料插入到指定Index的位置
StringBuffer delete(start,end);//刪除start(包含)到end(不包含)
等等。。可以去手冊查詢。這裡不再列出。
最後再舉個例子:
package com.test;public class test { public static void main(String[] args) { String[] arr=new String[10]; for(int i=0;i<arr.length;i++){ arr[i]="value"+i; } String result=""; for(String s:arr){//這個foreach語句產生了10個對象,九個沒用的垃圾對象,最終被GC回收,降低系統效能,最後只剩下一個我們想要的有<span style="white-space:pre"></span>//用的對象。 result+=s; } System.out.println(result); }} 輸出結果:
value0value1value2value3value4value5value6value7value8value9;
再舉一個例子:
String s=new String("abc");
上述語句中"abc"在編譯時間候,本身就是pool中的一個對象,而在運行時執行new String("abc")時,將pool中的對象複製一份放到heap中,並且把heap中的這個對象的引用交給了s。所以上面這句話,就建立了兩個String對象,一個在String pool 中一個在heap中。
例題:以下程式建立了幾個對象?
package com.test;public class test { public static void main(String[] args) { String A,B,C; A="a";//第一個對象 B="b";//第二個 A=A+B;//第三個,此時引用變數A指向"ab"對象,原來指向的"a"對象成為垃圾對象,會被GC回收 StringBuffer D=new StringBuffer("abc");//直接產生兩個對象。一個在string pool 一個在heap D=D.append("567");//在D對象本身上修改的操作,不產生新的對象。 }} 結論,一共產生了5個對象。
java中String stringBuffer StringBuider 深入理解