Java認(rèn)證考試:Java String常用方法詳解 本文首先講述了Java String的常用方法,詳解String中的final用法,,用String常量池問題的四個(gè)例子對(duì)String對(duì)象的intern方法理解和分析,。 String中的final用法和理解 final StringBuffer a = new StringBuffer(“111”); final StringBuffer b = new StringBuffer(“222”); a=b;//此句編譯不通過 final StringBuffer a = new StringBuffer(“111”); a.append(“222”);//編譯通過 可見,final只對(duì)引用的“值”(即內(nèi)存地址)有效,,它迫使引用只能指向初始指向的那個(gè)對(duì)象,,改變它的指向會(huì)導(dǎo)致編譯期錯(cuò)誤。至于它所指向的對(duì)象的變化,,final是不負(fù)責(zé)的。 String常量池問題的四個(gè)例子 下面是幾個(gè)常見例子的比較分析和理解: [1] String a = “a1”; String b = “a” + 1; System.out.println((a == b)); //result = true String a = “atrue”; String b = “a” + “true”; System.out.println((a == b)); //result = true String a = “a3.4”; String b = “a” + 3.4; System.out.println((a == b)); //result = true 分析:JVM對(duì)于字符串常量的“+”號(hào)連接,,將程序編譯期,,JVM就將常量字符串的“+”連接優(yōu)化為連接后的值,拿“a” + 1來說,,經(jīng)編譯器優(yōu)化后在class中就已經(jīng)是a1,。在編譯期其字符串常量的值就確定下來,故上面程序最終的結(jié)果都為true,。 [2] String a = “ab”; String bb = “b”; String b = “a” + bb; System.out.println((a == b)); //result = false 分析:JVM對(duì)于字符串引用,,由于在字符串的“+”連接中,有字符串引用存在,,而引用的值在程序編譯期是無法確定的,,即“a” + bb無法被編譯器優(yōu)化,只有在程序運(yùn)行期來動(dòng)態(tài)分配并將連接后的新地址賦給b,。所以上面程序的結(jié)果也就為false,。 [3] String a = “ab”; final String bb = “b”; String b = “a” + bb; System.out.println((a == b)); //result = true 分析:和[3]中唯一不同的是bb字符串加了final修飾,對(duì)于final修飾的變量,,它在編譯時(shí)被解析為常量值的一個(gè)本地拷貝存儲(chǔ)到自己的常量池中或嵌入到它的字節(jié)碼流中,。所以此時(shí)的“a” + bb和“a” + “b”效果是一樣的。故上面程序的結(jié)果為true,。 [4] String a = “ab”; final String bb = getBB(); String b = “a” + bb; System.out.println((a == b)); //result = false private static String getBB() { return “b”; } 分析:JVM對(duì)于字符串引用bb,,它的值在編譯期無法確定,,只有在程序運(yùn)行期調(diào)用方法后,將方法的返回值和“a”來動(dòng)態(tài)連接并分配地址為b,,故上面程序的結(jié)果為false,。 通過上面4個(gè)例子可以得出得知: String s = “a” + “b” + “c”; 就等價(jià)于String s = “abc”; String a = “a”; String b = “b”; String c = “c”; String s = a + b + c; 這個(gè)就不一樣了,最終結(jié)果等于: StringBuffer temp = new StringBuffer(); temp.append(a).append(b).append(c); String s = temp.toString(); 由上面的分析結(jié)果,,可就不難推斷出String 采用連接運(yùn)算符(+)效率低下原因分析,,形如這樣的代碼: public class Test { public static void main(String args[]) { String s = null; for(int i = 0; i 《 100; i++) { s += “a”; } } } 每做一次 + 就產(chǎn)生個(gè)StringBuilder對(duì)象,然后append后就扔掉,。下次循環(huán)再到達(dá)時(shí)重新產(chǎn)生個(gè)StringBuilder對(duì)象,,然后 append 字符串,如此循環(huán)直至結(jié)束,。 如果我們直接采用 StringBuilder 對(duì)象進(jìn)行 append 的話,,我們可以節(jié)省 N - 1 次創(chuàng)建和銷毀對(duì)象的時(shí)間。所以對(duì)于在循環(huán)中要進(jìn)行字符串連接的應(yīng)用,,一般都是用StringBuffer或StringBulider對(duì)象來進(jìn)行append操作,。 String對(duì)象的intern方法理解和分析 public class Test4 { private static String a = “ab”; public static void main(String[] args){ String s1 = “a”; String s2 = “b”; String s = s1 + s2; System.out.println(s == a);//false System.out.println(s.intern() == a);//true } } 這里用到Java里面是一個(gè)常量池的問題。對(duì)于s1+s2操作,,其實(shí)是在堆里面重新創(chuàng)建了一個(gè)新的對(duì)象,,s保存的是這個(gè)新對(duì)象在堆空間的的內(nèi)容,所以s與a的值是不相等的,。而當(dāng)調(diào)用s.intern()方法,,卻可以返回s在常量池中的地址值,因?yàn)閍的值存儲(chǔ)在常量池中,,故s.intern和a的值相等,。 |
|