版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認(rèn)領(lǐng)
文檔簡介
-JAVA程序員JAVA工程師面試必看JAVA面試題解惑系列(二)一一到底創(chuàng)建了幾個String對象?關(guān)鍵字:java面試題string創(chuàng)建幾個對象作者:臧圩人(zangweiren)網(wǎng)址:>>>轉(zhuǎn)載請注明出處!<<<我們首先來看一段代碼:Java代碼-■Stringstr=newString("abc");緊接著這段代碼之后的往往是這個問題,那就是這行代碼究竟創(chuàng)建了幾個String對象呢?相信大家對這道題并不陌生,答案也是眾所周知的,2個。接下來我們就從這道題展開,一起回顧一下與創(chuàng)建String對象相關(guān)的一些JAVA知識。我們可以把上面這行代碼分成Stringstr、=、"abc"和newString()四部分來看待。Stringstr只是定義了一個名為str的String類型的變量,因此它并沒有創(chuàng)建對象;=是對變量str進行初始化,將某個對象的引用(或者叫句柄)賦值給它,顯然也沒有創(chuàng)建對象;現(xiàn)在只剩下newString("abc")了。那么,newString("abc")為什么又能被看成"abc"和newString()呢?我們來看一下被我們調(diào)用了的String的構(gòu)造器:Java代碼-■publicString(Stringoriginal){//othercode...}大家都知道,我們常用的創(chuàng)建一個類的實例(對象)的方法有以下兩種使用new創(chuàng)建對象。調(diào)用Class類的newInstance方法,利用反射機制創(chuàng)建對象。我們正是使用new調(diào)用了String類的上面那個構(gòu)造器方法創(chuàng)建了一個對象,并將它的引用賦值給了str變量。同時我們注意到,被調(diào)用的構(gòu)造器方法接受的參數(shù)也是一個String對象,這個對象正是"abc"。由此我們又要引入另外一種創(chuàng)建String對象的方式的討論——引號內(nèi)包含文本。這種方式是String特有的,并且它與new的方式存在很大區(qū)別。Java代碼Stringstr="abc";毫無疑問,這行代碼創(chuàng)建了一個String對象。Java代碼Stringa="abc";Stringb="abc";
那這里呢?答案還是一個。Java代碼Stringa="ab"+"cd";再看看這里呢?答案仍是一個。有點奇怪嗎?說到這里,我們就需要引入對字符串池相關(guān)知識的回顧了。在JAVA虛擬機(JVM)中存在著一個字符串池,其中保存著很多String對象,并且可以被共享使用,因此它提高了效率。由于String類是final的,它的值一經(jīng)創(chuàng)建就不可改變,因此我們不用擔(dān)心String對象共享而帶來程序的混亂。字符串池由String類維護,我們可以調(diào)用intern()方法來訪問字符串池。我們再回頭看看Stringa="abc";,這行代碼被執(zhí)行的時候,JAVA虛擬機首先在字符串池中查找是否已經(jīng)存在了值為"abc"的這么一個對象,它的判斷依據(jù)是String類equals(Objectobj)方法的返回值。如果有,則不再創(chuàng)建新的對象,直接返回已存在對象的引用;如果沒有,則先創(chuàng)建這個對象,然后把它加入到字符串池中,再將它的引用返回。因此,我們不難理解前面三個例子中頭兩個例子為什么是這個答案了。對于第三個例子:Java代碼Stringa="ab"+"cd";由于常量的值在編譯的時候就被確定了。在這里,"ab"和"cd"都是常量,因此變量a的值在編譯時就可以確定。這行代碼編譯后的效果等同于:Java代碼—Stringa="abcd";因此這里只創(chuàng)建了一個對象"abcd",并且它被保存在字符串池里了?,F(xiàn)在問題又來了,是不是所有經(jīng)過“+”連接后得到的字符串都會被添加到字符串池中呢?我們都知道“==”可以用來比較兩個變量,它有以下兩種情況:如果比較的是兩個基本類型(char,byte,short,int,long,float,double,boolean),則是判斷它們的值是否相等。如果表較的是兩個對象變量,則是判斷它們的引用是否指向同一個對象。下面我們就用“==”來做幾個測試。為了便于說明,我們把指向字符串池中已經(jīng)存在的對象也視為該對象被加Java代碼....10.publicstaticvoidmain(String[]args){Stringa="ab";//創(chuàng)建了一個對象,并加入字符串池中System.out.println("Stringa=\"ab\";");Stringb="cd";//創(chuàng)建了一個對象,并加入字符串池中System.out.println("Stringb=\"cd\";");Stringc="abed";//創(chuàng)建了一個對象,并加入字符串池中Stringd="ab"+"cd";//如果d和c指向了同一個對象,則說明d也被加入了字符串池
if(d==c){System.out.println("\"ab\"+\"cd\"創(chuàng)建的對象\"加入了\"字符串池中");TOC\o"1-5"\h\z}//如果d和c沒有指向了同一個對象,則說明d沒有被加入字符串池else{System.out.println("\"ab\"+\"cd\"創(chuàng)建的對象\"沒加入\"字符串池中”);}18.Stringe=a+"cd";//如果e和c指向了同一個對象,則說明e也被加入了字符串池if(e==c) {System.out.println(”a+\"cd\"創(chuàng)建的對象\"加入了\"字符串池中”);}//如果e和c沒有指向了同一個對象,則說明e沒有被加入字符串池else{System.out.println("a+\"cd\"創(chuàng)建的對象\"沒加入\"字符串池中");}28.Stringf="ab"+b;//如果f和c指向了同一個對象,則說明f也被加入了字符串池if(f== c){System.out.println("\"ab\"+b創(chuàng)建的對象\"加入了\"字符串池中");}//如果f和c沒有指向了同一個對象,則說明f沒有被加入字符串池else{System.out.println("\"ab\"+b創(chuàng)建的對象\"沒加入\"字符串池中");}38.Stringg=a+b;//如果g和c指向了同一個對象,則說明g也被加入了字符串池if(g==c){System.out.println("a+b創(chuàng)建的對象\"加入了\"字符串池中");TOC\o"1-5"\h\z}//如果g和c沒有指向了同一個對象,則說明g沒有被加入字符串池else{System.out.println("a+b創(chuàng)建的對象\"沒加入\"字符串池中");}}}運行結(jié)果如下:Stringa="ab";Stringb="cd";"ab"+"cd"創(chuàng)建的對象"加入了"字符串池中a+"cd"創(chuàng)建的對象"沒加入"字符串池中"ab"+b創(chuàng)建的對象"沒加入"字符串池中a+b創(chuàng)建的對象"沒加入"字符串池中從上面的結(jié)果中我們不難看出,只有使用引號包含文本的方式創(chuàng)建的String對象之間使用“+”連接產(chǎn)生的新對象才會被加入字符串池中。對于所有包含new方式新建對象(包括null)的“+”連接表達式,它所產(chǎn)生的新對象都不會被加入字符串池中,對此我們不再贅述。但是有一種情況需要引起我們的注意。請看下面的代碼:Java代碼1. publicclassStringStaticTest{//常量ApublicstaticfinalStringA="ab";4.//常量BpublicstaticfinalStringB="cd";7.publicstaticvoidmain(String[]args){//將兩個常量用+連接對s進行初始化Strings=A+B;Stringt="abcd";if(s==t){System.out.println("s等于t,它們是同一個對象");}else{System.out.println("s不等于t,它們不是同一個對象");}}}這段代碼的運行結(jié)果如下:s等于t,它們是同一個對象這又是為什么呢?原因是這樣的,對于常量來講,它的值是固定的,因此在編譯期就能被確定了,而變量的值只有到運行時才能被確定,因為這個變量可以被不同的方法調(diào)用,從而可能引起值的改變。在上面的例子中,A和B都是常量,值是固定的,因此s的值也是固定的,它在類被編譯時就已經(jīng)確定了。也就是說:Java代碼1.Strings=A+B;等同于:Java代碼—1.Strings="ab"+"cd";我對上面的例子稍加改變看看會出現(xiàn)什么情況:Java代碼publicclassStringStaticTest{//常量ApublicstaticfinalStringA;4.//常量BpublicstaticfinalStringB;7.static{A="ab";B="cd";}12.publicstaticvoidmain(String[]args){//將兩個常量用+連接對s進行初始化15.Strings=A+B;16.Stringt="abcd";17.if(s==t){18.System.out.println("s等于t,它們是同一個對象");19.}else{20.System.out.println("s不等于t,它們不是同一個對象”);21.}22.}23.}它的運行結(jié)果是這樣:s不等于t,它們不是同一個對象只是做了一點改動,結(jié)果就和剛剛的例子恰好相反。我們再來分析一下。A和B雖然被定義為常量(只能被賦值一次),但是它們都沒有馬上被賦值。在運算出s的值之前,他們何時被賦值,以及被賦予什么樣的值,都是個變數(shù)。因此A和B在被賦值之前,性質(zhì)類似于一個變量。那么s就不能在編譯期被確定,而只能在運行時被創(chuàng)建了。由于字符串池中對象的共享能夠帶來效率的提高,因此我們提倡大家用引號包含文本的方式來創(chuàng)建String對象,實際上這也是我們在編程中常采用的。接下來我們再來看看intern()方法,它的定義如下:Java代碼1.publicnativeStringintern();這是一個本地方法。在調(diào)用這個方法時,JAVA虛擬機首先檢查字符串池中是否已經(jīng)存在與該對象值相等對象存在,如果有則返回字符串池中對象的引用;如果沒有,則先在字符串池中創(chuàng)建一個相同值的String對象,然后再將它的引用返回。我們來看這段代碼:Java代碼publicclassStringInternTest{publicstaticvoidmain(String[]args){//使用char數(shù)組來初始化a,避免在a被創(chuàng)建之前字符串池中已經(jīng)存在了值為"abed"的對象Stringa=newString(newchar[]{'a','b','c','d'});Stringb = ern();if(b== a) {System.out.println("b被加入了字符串池中,沒有新建對象");}else{System.out.println("b沒被加入字符串池中,新建了對象”);}}}運行結(jié)果:b沒被加入字符串池中,新建了對象如果String類的intern()方法在沒有找到相同值的對象時,是把當(dāng)前對象加入字符串池中,然后返回它的引用的話,那么b和a指向的就是同一個對象;否則b指向的對象就是JAVA虛擬機在字符串池中新建的,只是它的值與a相同罷了。上面這段代碼的運行結(jié)果恰恰印證了這一點。最后我們再來說說String對象在JAVA虛擬機(JVM)中的存儲,以及字符串池與堆(heap)和棧(stack)的關(guān)系。我們首先回顧一下堆和棧的區(qū)別:棧(stack):主要保存基本類型(或者叫內(nèi)置類型)(char、byte、short、int、long、float、double、boolean)和對象的引用,數(shù)據(jù)可以共享,速度僅次于寄存器(register),快于堆。堆(heap):用于存儲對象。我們查看String類的源碼就會發(fā)現(xiàn),它有一個value屬性,保存著String對象的值,類型是char[],這也正說明了字符串就是字符的序列。當(dāng)執(zhí)行Stringa="abc";時,JAVA虛擬機會在棧中創(chuàng)建三個char型的值'a'、'b'和'c',然后在堆中創(chuàng)建一個String對象,它的值(value)是剛才在棧中創(chuàng)建的三個char型值組成的數(shù)組{'a','b','c'},最后這個新創(chuàng)建的String對象會被添加到字符串池中。如果我們接著執(zhí)行Stringb=newString("abc");代碼,由于"abc"已經(jīng)被創(chuàng)建并保存于字符串池中,因此JAVA虛擬機只會在堆中新創(chuàng)建一個String對象,但是它的值(value)是共享前一行代碼執(zhí)行時在棧中創(chuàng)建的三個char型值值'a'、’b'和'c'。說到這里,我們對于篇首提出的Stringstr=newString("abc")為什么是創(chuàng)建了兩個對象這個問題就已經(jīng)相當(dāng)明了了。?18:45?瀏覽(4398)評論(58)分類:JAVA面試題解惑系列收藏相關(guān)推薦評論臧圩人4小時前回復(fù)disorder:因為是使用new創(chuàng)建的,因此沒有加入到字符串池中,但是你可以調(diào)用intern()方法來手動實現(xiàn)這一步disorder4小時前請問一下為什么這里a就沒有被加入到池中呢?Java代碼1.Stringa=newString(newchar[]{'a','b','c','d'});臧圩人前天回復(fù)viMory:你引用的那段話所講的是對的,但是在我所舉的例子中,由于我給出的示例代碼前沒有其它代碼執(zhí)行,因此"abc"不會被創(chuàng)建出來viMory2008-07-14引用這個還與具體的條件相關(guān),如果在String池中沒有“abc”對象存在那么就會創(chuàng)建兩個對象,如果池中已經(jīng)存在“abc”對象的話,那么就只是創(chuàng)建一個對象,所以這個問題要看具體的條件才能下結(jié)論我也同意這句,已經(jīng)存在的話就是一個對象了。LZ你認(rèn)為有可能不?Bluesnails2008-07-14看了前兩章,總結(jié)的很詳細啊,受教了?zm26934502008-07-14好貼,頂起來臧圩人2008-07-13回復(fù)chq32:這位朋友,不知你是沒看全還是沒看仔細我很明確地說了Stringstr只是定義了一個變量并沒有創(chuàng)建對象,真正創(chuàng)建對象的是"abc"和newString。chq322008-07-13我總覺得是一個對象。Stringstr=newString("abc");用"人"來比喻的話,,"str"相當(dāng)于人的身證證,"abc"相當(dāng)于人的肉身你能說是兩個人嗎??我不解如果按樓主說的是兩個對象,那我看所有的對象都是兩個對象了臧圩人2008-07-09回復(fù)狂放不羈:你說得對。不過我寫這系列文章的目的是面試題解惑,和鞏固基礎(chǔ)知識,如果想要做好J2EE企業(yè)級開發(fā),就需要更進一步的學(xué)習(xí)了狂放不羈2008-07-08呵呵,這種考題也就只能考考J2SE基礎(chǔ)。做J2EE企業(yè)級開發(fā),設(shè)計模式,00思想才是重點。臧圩人2008-07-06回復(fù)Unmi:呵呵,一個人的能力固然不是單憑面試就能夠完全考出來的,但是出面試題不失為一個不錯的考查方法,而分00.析面試題也不失為一個有針對性的好的學(xué)習(xí)途徑Unmi2008-07-06我覺得出這個題目的人很無聊,分析這個問題的更是無聊,有意思嗎?迂腐臧圩人2008-07-06回復(fù)zc2yhy:總結(jié)的很好我對于字符串池是這么理解的,它是內(nèi)存中的一塊內(nèi)存區(qū)域,作用可以類比于數(shù)組(當(dāng)然,字符串池并不是對oc.象),字符串池中保存的只是對象的引用,實際的對象只在堆中保存一份。zc,2yhy2008-07-05讓小弟來小結(jié)一下這篇文章所說的事情吧堆和棧的概念。編譯器也是很機械化的,只能一行行的讀代碼,所以,在有的時候看似為靜態(tài)的值,其實編譯器是看不出來的,它也只能當(dāng)機立斷得判斷。3?看完后感覺在lz所說的字符串池中存儲的其實也是基本數(shù)據(jù)類型char的數(shù)組或者說序列char[],在String類中將其包裝。在vb還是c#中我忘了,就區(qū)分了這兩種字符串的概念,分為基本類型string和對象類型String(注意大小寫)。4?在這里完全能感受到創(chuàng)作一個完整、封閉的語言是多么的縝密于細致,其實這也取決于當(dāng)時Gosling或其開發(fā)團隊的想法,當(dāng)然作為這么優(yōu)秀的語言,我們確實應(yīng)該學(xué)習(xí)得更加細致。臧圩人2008-07-04回復(fù)sooo:你的理解是對的,最后一例中,a的確沒有被加入字符串池中,而b被加入了。而對于這句話:
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025公路施工勞務(wù)承包合同
- 2025企業(yè)管理資料員工訴企業(yè)“乘人之?!焙炗喰薷膭趧雍贤趺崔k文檔范本
- 2025合同模板合作辦幼兒園合同范本
- 2025國際銷售代表合同
- 胎兒保護科學(xué)指導(dǎo)下的孕婦藥物選擇
- 結(jié)合現(xiàn)代科技的自然體驗課程設(shè)計探討
- 2024年拉米夫定項目資金需求報告代可行性研究報告
- 2024年O型圈項目投資申請報告代可行性研究報告
- 生態(tài)農(nóng)業(yè)科技發(fā)展現(xiàn)狀與前景展望
- 二零二五年度新能源發(fā)電項目電氣設(shè)備安裝調(diào)試合同4篇
- 2024-2025學(xué)年山東省濰坊市高一上冊1月期末考試數(shù)學(xué)檢測試題(附解析)
- 江蘇省揚州市蔣王小學(xué)2023~2024年五年級上學(xué)期英語期末試卷(含答案無聽力原文無音頻)
- 數(shù)學(xué)-湖南省新高考教學(xué)教研聯(lián)盟(長郡二十校聯(lián)盟)2024-2025學(xué)年2025屆高三上學(xué)期第一次預(yù)熱演練試題和答案
- 決勝中層:中層管理者的九項修煉-記錄
- 幼兒園人民幣啟蒙教育方案
- 軍事理論(2024年版)學(xué)習(xí)通超星期末考試答案章節(jié)答案2024年
- 記錄片21世紀(jì)禁愛指南
- 腰椎間盤的診斷證明書
- 移動商務(wù)內(nèi)容運營(吳洪貴)任務(wù)七 裂變傳播
- 單級倒立擺系統(tǒng)建模與控制器設(shè)計
- 齲病的治療 深齲的治療
評論
0/150
提交評論