關(guān)于Java String對(duì)象創(chuàng)建問題解惑
本文為原創(chuàng),如需轉(zhuǎn)載,請(qǐng)注明作者和出處,謝謝!
先看看下面的代碼
public String makinStrings()
{
String s = "Fred";
s = s + "47";
s = s.substring(2, 5);
s = s.toUpperCase();
return s.toString();
}
問:調(diào)用makinStrings方法會(huì)創(chuàng)建幾個(gè)String對(duì)象呢。 答案:3個(gè)
上面的方法有五條語(yǔ)句:現(xiàn)在讓我們來(lái)一條一條分析一下。
String s = "Fred"; 結(jié)論:創(chuàng)建了一個(gè)String對(duì)象
這條語(yǔ)句相當(dāng)于String s = new String("Fred");
因此,毫無(wú)疑問,第一條語(yǔ)句創(chuàng)建了一個(gè)String對(duì)象,我想沒有有疑問吧?
s = s + "47"; 結(jié)論:未創(chuàng)建String對(duì)象
這條語(yǔ)句也許很多人認(rèn)為是創(chuàng)建了String對(duì)象,我一開始也是這么認(rèn)為的。但是為了驗(yàn)證我的想法。決定
用點(diǎn)法術(shù)恢復(fù)這條語(yǔ)句的本來(lái)面目。(有很多時(shí)候,編譯器總是在里面搞一些小動(dòng)作,javac.exe也不例外)
現(xiàn)在找到這個(gè)程序所生成的.class文件(假設(shè)是Test.class),找一個(gè)反編譯工具,我推薦JAD,可以http://www.softpedia.com/progDownload/JAD-Download-85911.html下載
下載后,有一個(gè)jad.exe,將其路徑放到環(huán)境變量path中(只限windows)。并在.class文件的當(dāng)前路徑執(zhí)行如下的命令:
jad Test
然后大喊一聲“還我本來(lái)面目”
會(huì)在當(dāng)前目錄下生成一個(gè)Test.jad文件,打開它,文件內(nèi)容如下:

public String makinStrings()
{
String s = "Fred";
s = (new StringBuilder(String.valueOf(s))).append("47").toString();
s = s.substring(2, 5);
s = s.toUpperCase();
return s.toString();
}
哈哈,其他的語(yǔ)句都沒變,只有第二條變長(zhǎng)了,雖然多了個(gè)new,但是建立的是StringBuilder對(duì)象。原來(lái)
這是java編譯器的優(yōu)化處理。原則是能不建String對(duì)象就不建String對(duì)象。而是用StringBuilder對(duì)象
加這些字符串連接起來(lái),相當(dāng)于一個(gè)字符串隊(duì)列。這種方式尤其被使用在循環(huán)中,大家可以看看下面的代碼:
String s = "";
for(int i=0; i < 10000000; i++)
s += "aa";
沒有哪位老大認(rèn)為這是建立了10000000個(gè)String對(duì)象吧。但不幸的是,上面的代碼雖然沒有建立10000000個(gè)String對(duì)象
但卻建立了10000000個(gè)StringBuilder對(duì)象,那是為什么呢,自已用jad工具分析一下吧。
正確的寫法應(yīng)該是:
StringBuilder sb = new StringBuilder("");
for(int i=0; i < 10000000; i++)
sb.append(String.valueOf(i));
s = s.substring(2, 5); 結(jié)論:創(chuàng)建了一個(gè)String對(duì)象
也許有很多人一開始就認(rèn)為這條語(yǔ)句是創(chuàng)建了一個(gè)String對(duì)象,那么恭喜你,這條語(yǔ)句確實(shí)創(chuàng)建了一個(gè)String對(duì)象
實(shí)際上就是substring方法創(chuàng)建了一個(gè)String對(duì)象。這也沒什么復(fù)雜的,自已下一個(gè)JDK源代碼,看看substring是如何實(shí)現(xiàn)的
就可以知道了。我先說(shuō)一下吧。先不用管substring是如何實(shí)現(xiàn)的,反正在substring方法返回時(shí)使用了一個(gè)new顯式地建立了一個(gè)String對(duì)象
不信自己看看源碼。
s = s.toUpperCase(); 結(jié)論:創(chuàng)建了一個(gè)String對(duì)象
toUpperCase()和substring方法類似,在返回時(shí)也是使用了new建立了一個(gè)String對(duì)象。
return s.toString(); 結(jié)論:未創(chuàng)建String對(duì)象
toString方法返回的就是this,因此,它的返回值就是s。
這道題還算比較簡(jiǎn)單,再給大家出一個(gè)更復(fù)雜一點(diǎn)的,也是關(guān)于String對(duì)象的創(chuàng)建的(只是改了一個(gè)原題)。
先公布答案吧,上述代碼也創(chuàng)建了3個(gè)String對(duì)象,哈哈!
為什么呢?
要想知道為什么,先得弄清楚substring、toLowerCase和toUpperCase什么時(shí)候創(chuàng)建String對(duì)象,什么時(shí)候不創(chuàng)建對(duì)象。
substring方法在截取的子字符串長(zhǎng)度等于原字符串時(shí),直接返回原字符串。并不創(chuàng)建新的String對(duì)象。
toLowerCase方法在字符串中更本沒有需要轉(zhuǎn)換的大寫字母時(shí)直接返回原字符串,如"abcd".toLowerCase()直接返回abcd,并不創(chuàng)建新的String對(duì)象
toUpperCase方法和toLowerCase類似。"ABCD".toUpperCase()直接返回ABCD。
知道了這個(gè),上面的代碼就非常清楚了。
新浪微博:http://t.sina.com.cn/androidguy 昵稱:李寧_Lining
先看看下面的代碼
public String makinStrings()
{
String s = "Fred";
s = s + "47";
s = s.substring(2, 5);
s = s.toUpperCase();
return s.toString();
}
問:調(diào)用makinStrings方法會(huì)創(chuàng)建幾個(gè)String對(duì)象呢。 答案:3個(gè)
上面的方法有五條語(yǔ)句:現(xiàn)在讓我們來(lái)一條一條分析一下。
String s = "Fred"; 結(jié)論:創(chuàng)建了一個(gè)String對(duì)象
這條語(yǔ)句相當(dāng)于String s = new String("Fred");
因此,毫無(wú)疑問,第一條語(yǔ)句創(chuàng)建了一個(gè)String對(duì)象,我想沒有有疑問吧?
s = s + "47"; 結(jié)論:未創(chuàng)建String對(duì)象
這條語(yǔ)句也許很多人認(rèn)為是創(chuàng)建了String對(duì)象,我一開始也是這么認(rèn)為的。但是為了驗(yàn)證我的想法。決定
用點(diǎn)法術(shù)恢復(fù)這條語(yǔ)句的本來(lái)面目。(有很多時(shí)候,編譯器總是在里面搞一些小動(dòng)作,javac.exe也不例外)
現(xiàn)在找到這個(gè)程序所生成的.class文件(假設(shè)是Test.class),找一個(gè)反編譯工具,我推薦JAD,可以http://www.softpedia.com/progDownload/JAD-Download-85911.html下載
下載后,有一個(gè)jad.exe,將其路徑放到環(huán)境變量path中(只限windows)。并在.class文件的當(dāng)前路徑執(zhí)行如下的命令:
jad Test
然后大喊一聲“還我本來(lái)面目”
會(huì)在當(dāng)前目錄下生成一個(gè)Test.jad文件,打開它,文件內(nèi)容如下:


public String makinStrings()
{
String s = "Fred";
s = (new StringBuilder(String.valueOf(s))).append("47").toString();
s = s.substring(2, 5);
s = s.toUpperCase();
return s.toString();
}


哈哈,其他的語(yǔ)句都沒變,只有第二條變長(zhǎng)了,雖然多了個(gè)new,但是建立的是StringBuilder對(duì)象。原來(lái)
這是java編譯器的優(yōu)化處理。原則是能不建String對(duì)象就不建String對(duì)象。而是用StringBuilder對(duì)象
加這些字符串連接起來(lái),相當(dāng)于一個(gè)字符串隊(duì)列。這種方式尤其被使用在循環(huán)中,大家可以看看下面的代碼:
String s = "";
for(int i=0; i < 10000000; i++)
s += "aa";
沒有哪位老大認(rèn)為這是建立了10000000個(gè)String對(duì)象吧。但不幸的是,上面的代碼雖然沒有建立10000000個(gè)String對(duì)象
但卻建立了10000000個(gè)StringBuilder對(duì)象,那是為什么呢,自已用jad工具分析一下吧。
正確的寫法應(yīng)該是:
StringBuilder sb = new StringBuilder("");
for(int i=0; i < 10000000; i++)
sb.append(String.valueOf(i));
s = s.substring(2, 5); 結(jié)論:創(chuàng)建了一個(gè)String對(duì)象
也許有很多人一開始就認(rèn)為這條語(yǔ)句是創(chuàng)建了一個(gè)String對(duì)象,那么恭喜你,這條語(yǔ)句確實(shí)創(chuàng)建了一個(gè)String對(duì)象
實(shí)際上就是substring方法創(chuàng)建了一個(gè)String對(duì)象。這也沒什么復(fù)雜的,自已下一個(gè)JDK源代碼,看看substring是如何實(shí)現(xiàn)的
就可以知道了。我先說(shuō)一下吧。先不用管substring是如何實(shí)現(xiàn)的,反正在substring方法返回時(shí)使用了一個(gè)new顯式地建立了一個(gè)String對(duì)象
不信自己看看源碼。
s = s.toUpperCase(); 結(jié)論:創(chuàng)建了一個(gè)String對(duì)象
toUpperCase()和substring方法類似,在返回時(shí)也是使用了new建立了一個(gè)String對(duì)象。
return s.toString(); 結(jié)論:未創(chuàng)建String對(duì)象
toString方法返回的就是this,因此,它的返回值就是s。
這道題還算比較簡(jiǎn)單,再給大家出一個(gè)更復(fù)雜一點(diǎn)的,也是關(guān)于String對(duì)象的創(chuàng)建的(只是改了一個(gè)原題)。
public String makinStrings()
{
String s = "Fred";
s = s + "Iloveyou.".substring(1).toLowerCase();
s = s.substring(0);
s = s.substring(0,1).toUpperCase();
return s.toString();
}
{
String s = "Fred";
s = s + "Iloveyou.".substring(1).toLowerCase();
s = s.substring(0);
s = s.substring(0,1).toUpperCase();
return s.toString();
}
先公布答案吧,上述代碼也創(chuàng)建了3個(gè)String對(duì)象,哈哈!
為什么呢?
要想知道為什么,先得弄清楚substring、toLowerCase和toUpperCase什么時(shí)候創(chuàng)建String對(duì)象,什么時(shí)候不創(chuàng)建對(duì)象。
substring方法在截取的子字符串長(zhǎng)度等于原字符串時(shí),直接返回原字符串。并不創(chuàng)建新的String對(duì)象。
toLowerCase方法在字符串中更本沒有需要轉(zhuǎn)換的大寫字母時(shí)直接返回原字符串,如"abcd".toLowerCase()直接返回abcd,并不創(chuàng)建新的String對(duì)象
toUpperCase方法和toLowerCase類似。"ABCD".toUpperCase()直接返回ABCD。
知道了這個(gè),上面的代碼就非常清楚了。
public String makinStrings()
{
String s = "Fred"; // 創(chuàng)建一個(gè)String對(duì)象
s = s + "Iloveyou.".substring(1).toLowerCase(); // substring(1)創(chuàng)建一個(gè)String對(duì)象,由于toLowerCase()轉(zhuǎn)換的字符串是"loveyou.",沒有大寫字母,因此,它不創(chuàng)建新的String對(duì)象
s = s.substring(0); // 由于substring(0)截獲的是s本身,因此,這條語(yǔ)句不創(chuàng)建新的String對(duì)象
s = s.substring(0,1).toUpperCase(); // substring(0,1)創(chuàng)建了一個(gè)String對(duì)象,但由于substring(0,1)的結(jié)果是"F",為一個(gè)大寫字母,因此,toUpperCase直接返回"F"本身。
return s.toString();
}
{
String s = "Fred"; // 創(chuàng)建一個(gè)String對(duì)象
s = s + "Iloveyou.".substring(1).toLowerCase(); // substring(1)創(chuàng)建一個(gè)String對(duì)象,由于toLowerCase()轉(zhuǎn)換的字符串是"loveyou.",沒有大寫字母,因此,它不創(chuàng)建新的String對(duì)象
s = s.substring(0); // 由于substring(0)截獲的是s本身,因此,這條語(yǔ)句不創(chuàng)建新的String對(duì)象
s = s.substring(0,1).toUpperCase(); // substring(0,1)創(chuàng)建了一個(gè)String對(duì)象,但由于substring(0,1)的結(jié)果是"F",為一個(gè)大寫字母,因此,toUpperCase直接返回"F"本身。
return s.toString();
}
《Android開發(fā)完全講義(第2版)》(本書版權(quán)已輸出到臺(tái)灣)
http://product.dangdang.com/product.aspx?product_id=22741502
《Android高薪之路:Android程序員面試寶典 》http://book.360buy.com/10970314.html
新浪微博:http://t.sina.com.cn/androidguy 昵稱:李寧_Lining
posted on 2008-04-27 10:01 銀河使者 閱讀(3173) 評(píng)論(18) 編輯 收藏 所屬分類: java 、 原創(chuàng)