字符串連接可以通過(guò)兩種方法實(shí)現(xiàn)身隐,其中一種是在Java中提供的一個(gè)StringBuilder類(lèi)(這個(gè)類(lèi)只在J2SE5及以上版本提供廷区,以前的版本使用StringBuffer類(lèi))。
字符串是Java程序中最常用的一種數(shù)據(jù)結(jié)構(gòu)之一贾铝。在Java中的String類(lèi)已經(jīng)重載的"+"隙轻。也就是說(shuō),字符串可以直接使用"+"進(jìn)行連接垢揩,如下面代碼所示:
String s = "abc" + "ddd";
但這樣做真的好嗎玖绿?當(dāng)然,這個(gè)問(wèn)題不能簡(jiǎn)單地回答yes or no叁巨。要根據(jù)具體情況來(lái)定斑匪。在Java中提供了一個(gè)StringBuilder類(lèi)(這個(gè)類(lèi)只在J2SE5及以上版本提供,以前的版本使用StringBuffer類(lèi))锋勺,這個(gè)類(lèi)也可以起到"+"的作用蚀瘸。那么我們應(yīng)該用哪個(gè)呢?
下面讓我們先看看如下的代碼:
public class TestSimplePlus
{
public static void main(String[] args)
{
String s = "abc";
String ss = "ok" + s + "xyz" + 5;
System.out.println(ss);
}
}
上面的代碼將會(huì)輸出正確的結(jié)果庶橱。從表面上看贮勃,對(duì)字符串和整型使用"+"號(hào)并沒(méi)有什么區(qū)別,但事實(shí)真的如此嗎悬包?下面讓我們來(lái)看看這段代碼的本質(zhì)衙猪。
我們首先使用反編譯工具(如jdk帶的javap、或jad)將TestSimplePlus反編譯成Java Byte Code,其中的奧秘就一目了然了垫释。
通過(guò)反編譯得出的結(jié)果是:雖然在源程序中使用了"+"丝格,但在編譯時(shí)仍然將"+"轉(zhuǎn)換成StringBuilder。因此棵譬,我們可以得出結(jié)論显蝌,在Java中無(wú)論使用何種方式進(jìn)行字符串連接,實(shí)際上都使用的是StringBuilder類(lèi)订咸。
那么是不是可以根據(jù)這個(gè)結(jié)論推出使用"+"和StringBuilder類(lèi)的效果是一樣的呢曼尊?這個(gè)要從兩個(gè)方面的解釋。如果從運(yùn)行結(jié)果來(lái)解釋?zhuān)敲?+"和StringBuilder是完全等效的脏嚷。但如果從運(yùn)行效率和資源消耗方面看骆撇,那它們將存在很大的區(qū)別。
當(dāng)然父叙,如果連接字符串行表達(dá)式很簡(jiǎn)單(如上面的順序結(jié)構(gòu))神郊,那么"+"和StringBuilder類(lèi)基本是一樣的,但如果結(jié)構(gòu)比較復(fù)雜趾唱,如使用循環(huán)來(lái)連接字符串涌乳,那么產(chǎn)生的Java Byte Code(java字節(jié)碼)就會(huì)有很大的區(qū)別。先讓我們看看如下的代碼:
public class TestStringBuilder
{
public static void main(String[] args)
{
String s = "";
Random rand = new Random();
for (int i = 0; i < 10; i++)
{
result.append("a");
result.append(" ");
}
System.out.println(result.toString());
}
}
上面的代碼返編譯后可知甜癞,雖然編譯器將"+"轉(zhuǎn)換成了StringBuilder類(lèi)夕晓,但創(chuàng)建StringBuilder對(duì)象的位置卻在for語(yǔ)句內(nèi)部。這就意味著每執(zhí)行一次循環(huán)悠咱,就會(huì)創(chuàng)建一個(gè)StringBuilder對(duì)象(對(duì)于本例來(lái)說(shuō)蒸辆,是創(chuàng)建了10個(gè)StringBuilder對(duì)象),雖然Java有垃圾回收器乔煞,但這個(gè)回收器的工作時(shí)間是不定的吁朦。如果不斷產(chǎn)生這樣的垃圾,那么仍然會(huì)占用大量的資源渡贾。解決這個(gè)問(wèn)題的方法就是在程序中直接使用StringBuilder類(lèi)來(lái)連接字符串逗宜,代碼如下:
public class TestStringBuilder
{
public static void main(String[] args)
{
StringBuilder result = new StringBuilder();
for (int i = 0; i < 10; i++)
{
result.append("a");
result.append(" ");
}
System.out.println(result.toString());
}
}
創(chuàng)建StringBuilder的代碼被放在了for語(yǔ)句外。雖然這樣處理在源程序中看起來(lái)復(fù)雜空骚,但卻換來(lái)了更高的效率纺讲,同時(shí)消耗的資源也更少了。
在使用StringBuilder類(lèi)時(shí)要注意囤屹,盡量不要"+"和StringBuilder混著用熬甚,否則會(huì)創(chuàng)建更多的StringBuilder對(duì)象,如下面代碼所:
for (int i = 0; i < 10; i++)
{
result.append(rand.nextInt(1000));
result.append(" ");
}
改成:
for (int i=0;i<10;i++)
{
result.append(rand.nextIne(1000) + "")
}
如果將上面的代碼在JDK1.4下編譯肋坚,必須將StringBuilder改為StringBuffer乡括,而JDK1.4將"+"轉(zhuǎn)換為StringBuffer(因?yàn)镴DK1.4并沒(méi)有提供StringBuilder類(lèi))肃廓。StringBuffer和StringBuilder的功能基本一樣,只是StringBuffer是線程安全的诲泌,而StringBuilder不是線程安全的盲赊。因此,StringBuilder的效率會(huì)更高敷扫。