Stringstr=new String("abc") 這行代碼究竟創(chuàng)建了幾個(gè)對(duì)象?
Stringstr=new String("abc"); ? 緊接著這段代碼之后的往往是這個(gè)問(wèn)題突琳,那就是這行代碼究竟創(chuàng)建了幾個(gè)String對(duì)象呢若债?
相信大家對(duì)這道題并不陌生,答案也是眾所周知的拆融,2個(gè)蠢琳。
接下來(lái)我們就從這道題展開(kāi),一起回顧一下與創(chuàng)建String對(duì)象相關(guān)的一些JAVA知識(shí)镜豹。
我們可以把上面這行代碼分成Stringstr傲须、=、"abc"和new String()四部分來(lái)看待趟脂。Stringstr只是定義了一個(gè)名為str的String類型的變量泰讽,因此它并沒(méi)有創(chuàng)建對(duì)象;=是對(duì)變量str進(jìn)行初始化昔期,將某個(gè)對(duì)象的引用(或者叫句柄)賦值給它已卸,顯然也沒(méi)有創(chuàng)建對(duì)象;現(xiàn)在只剩下newString("abc")了硼一。那么累澡,newString("abc")為什么又能被看成"abc"和new String()呢?
我們來(lái)看一下被我們調(diào)用了的String的構(gòu)造器:
public String(String original) { ?//other code ... ?} ?大家都知道般贼,我們常用的創(chuàng)建一個(gè)類的實(shí)例(對(duì)象)的方法有以下兩種:
一永乌、使用new創(chuàng)建對(duì)象惑申。
二、調(diào)用Class類的newInstance方法翅雏,利用反射機(jī)制創(chuàng)建對(duì)象。
我們正是使用new調(diào)用了String類的上面那個(gè)構(gòu)造器方法創(chuàng)建了一個(gè)對(duì)象人芽,并將它的引用賦值給了str變量望几。同時(shí)我們注意到,被調(diào)用的構(gòu)造器方法接受的參數(shù)也是一個(gè)String對(duì)象萤厅,這個(gè)對(duì)象正是"abc"橄抹。由此我們又要引入另外一種創(chuàng)建String對(duì)象的方式的討論——引號(hào)內(nèi)包含文本。
這種方式是String特有的惕味,并且它與new的方式存在很大區(qū)別楼誓。
Stringstr="abc";
毫無(wú)疑問(wèn),這行代碼創(chuàng)建了一個(gè)String對(duì)象名挥。
Stringa="abc"; ?Stringb="abc"; ? 那這里呢疟羹?
答案還是一個(gè)。
Stringa="ab"+"cd"; ? 再看看這里呢禀倔?
答案是三個(gè)榄融。
說(shuō)到這里,我們就需要引入對(duì)字符串池相關(guān)知識(shí)的回顧了救湖。
在JAVA虛擬機(jī)(JVM)中存在著一個(gè)字符串池愧杯,其中保存著很多String對(duì)象,并且可以被共享使用鞋既,因此它提高了效率力九。由于String類是final的,它的值一經(jīng)創(chuàng)建就不可改變邑闺,因此我們不用擔(dān)心String對(duì)象共享而帶來(lái)程序的混亂跌前。字符串池由String類維護(hù),我們可以調(diào)用intern()方法來(lái)訪問(wèn)字符串池检吆。
我們?cè)倩仡^看看Stringa="abc";舒萎,這行代碼被執(zhí)行的時(shí)候,JAVA虛擬機(jī)首先在字符串池中查找是否已經(jīng)存在了值為"abc"的這么一個(gè)對(duì)象蹭沛,它的判斷依據(jù)是String類equals(Object obj)方法的返回值臂寝。如果有,則不再創(chuàng)建新的對(duì)象摊灭,直接返回已存在對(duì)象的引用咆贬;如果沒(méi)有,則先創(chuàng)建這個(gè)對(duì)象帚呼,然后把它加入到字符串池中掏缎,再將它的引用返回皱蹦。因此,我們不難理解前面三個(gè)例子中頭兩個(gè)例子為什么是這個(gè)答案了眷蜈。
只有使用引號(hào)包含文本的方式創(chuàng)建的String對(duì)象之間使用“+”連接產(chǎn)生的新對(duì)象才會(huì)被加入字符串池中沪哺。對(duì)于所有包含new方式新建對(duì)象(包括null)的“+”連接表達(dá)式,它所產(chǎn)生的新對(duì)象都不會(huì)被加入字符串池中酌儒,對(duì)此我們不再贅述辜妓。因此我們提倡大家用引號(hào)包含文本的方式來(lái)創(chuàng)建String對(duì)象以提高效率,實(shí)際上這也是我們?cè)诰幊讨谐2捎玫摹?/p>
棧(stack):主要保存基本類型(或者叫內(nèi)置類型)(char忌怎、byte籍滴、short、int榴啸、long孽惰、float、double鸥印、boolean)和對(duì)象的引用勋功,數(shù)據(jù)可以共享,速度僅次于寄存器(register)辅甥,快于堆酝润。
堆(heap):用于存儲(chǔ)對(duì)象
堆區(qū):主要存放Java程序運(yùn)行時(shí)創(chuàng)建的所有引用類型(new()生成的對(duì)象)都放在其中;
棧區(qū):主要存放Java程序運(yùn)行時(shí)所需的局部變量璃弄、方法的參數(shù)要销、對(duì)象的引用以及中間運(yùn)算結(jié)果等數(shù)據(jù);
代碼區(qū):主要存放Java的代碼夏块;
數(shù)據(jù)區(qū):主要存放靜態(tài)變量及全局變量 ?