String str=new String(“abc”); 緊接著這段代碼之后的往往是這個(gè)問題,那就是這行代碼究竟創(chuàng)建了幾個(gè)String對(duì)象呢?
相信大家對(duì)這道題并不陌生,答案也是眾所周知的琳水,2個(gè)。
接下來我們就從這道題展開般堆,一起回顧一下與創(chuàng)建String對(duì)象相關(guān)的一些JAVA知識(shí)在孝。
我們可以把上面這行代碼分成String str、=淮摔、"abc"和new String()四部分來看待私沮。String str只是定義了一個(gè)名為str的String類型的變量,因此它并沒有創(chuàng)建對(duì)象和橙;=是對(duì)變量str進(jìn)行初始化仔燕,將某個(gè)對(duì)象的引用(或者叫句柄)賦值給它,顯然也沒有創(chuàng)建對(duì)象魔招;現(xiàn)在只剩下new String(“abc”)了晰搀。那么,new String(“abc”)為什么又能被看成"abc"和new String()呢办斑?
我們來看一下被我們調(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ū)別。
String str=“abc”;
毫無疑問凛忿,這行代碼創(chuàng)建了一個(gè)String對(duì)象澈灼。
String a=“abc”; String b=“abc”; 那這里呢?
答案還是一個(gè)。
String a=“ab”+“cd”; 再看看這里呢叁熔?
答案是一個(gè)委乌。
乍一看是三個(gè),實(shí)際在編譯器,編譯器已經(jīng)對(duì)"ab"+"cd"做出了運(yùn)算,相當(dāng)于創(chuàng)建了"abcd"一個(gè)對(duì)象.
而且我們可以通過反編譯工具清楚地看出,這一步實(shí)際上就是String a = “abcd” .
說到這里,我們就需要引入對(duì)字符串池相關(guān)知識(shí)的回顧了荣回。
在JAVA虛擬機(jī)(JVM)中存在著一個(gè)字符串池遭贸,其中保存著很多String對(duì)象,并且可以被共享使用心软,因此它提高了效率壕吹。由于String類是final的,它的值一經(jīng)創(chuàng)建就不可改變删铃,因此我們不用擔(dān)心String對(duì)象共享而帶來程序的混亂耳贬。字符串池由String類維護(hù),我們可以調(diào)用intern()方法來訪問字符串池猎唁。
我們?cè)倩仡^看看String a=“abc”;咒劲,這行代碼被執(zhí)行的時(shí)候,JAVA虛擬機(jī)首先在字符串池中查找是否已經(jīng)存在了值為"abc"的這么一個(gè)對(duì)象诫隅,它的判斷依據(jù)是String類equals(Object obj)方法的返回值棱烂。如果有浪腐,則不再創(chuàng)建新的對(duì)象堕伪,直接返回已存在對(duì)象的引用窗市;如果沒有,則先創(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)包含文本的方式來創(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ì)象