天天看點

String s=new String("123")建立了幾個對象?

String str=new String("123");   緊接着這段代碼之後的往往是這個問題,那就是這行代碼究竟建立了幾個String對象呢?


相信大家對這道題并不陌生,答案也是衆所周知的,2個。


接下來我們就從這道題展開,一起回顧一下與建立String對象相關的一些JAVA知識。  


我們可以把上面這行代碼分成String str、=、"123"和new String()四部分來看待。String str隻是定義了一個名為str的String類型的變量,是以它并沒有建立對象;=是對變量str進行初始化,将某個對象的引用(或者叫句柄)指派給它,顯然也沒有建立對象;現在隻剩下new String("123")了。那麼,new String("123")為什麼又能被看成"123"和new String()呢?


我們來看一下被我們調用了的String的構造器:  


public String(String original) {  //other code ...  }   大家都知道,我們常用的建立一個類的執行個體(對象)的方法有以下兩種:


一、使用new建立對象。 


二、調用Class類的newInstance方法,利用反射機制建立對象。


我們正是使用new調用了String類的上面那個構造器方法建立了一個對象,并将它的引用指派給了str變量。同時我們注意到,被調用的構造器方法接受的參數也是一個String對象,這個對象正是"123"。由此我們又要引入另外一種建立String對象的方式的讨論——引号内包含文本。


 


這種方式是String特有的,并且它與new的方式存在很大差別。  


String str="123";  


毫無疑問,這行代碼建立了一個String對象。  


String a="123";  String b="123";   那這裡呢?


答案還是一個。  


String a="123"+"456";   再看看這裡呢?


答案是三個。
說到這裡,我們就需要引入對字元串池相關知識的回顧了。  


在JAVA虛拟機(JVM)中存在着一個字元串池,其中儲存着很多String對象,并且可以被共享使用,是以它提高了效率。由于String類是final的,它的值一經建立就不可改變,是以我們不用擔心String對象共享而帶來程式的混亂。字元串池由String類維護,我們可以調用intern()方法來通路字元串池。  


我們再回頭看看String a="123";,這行代碼被執行的時候,JAVA虛拟機首先在字元串池中查找是否已經存在了值為"123"的這麼一個對象,它的判斷依據是String類equals(Object obj)方法的傳回值。如果有,則不再建立新的對象,直接傳回已存在對象的引用;如果沒有,則先建立這個對象,然後把它加入到字元串池中,再将它的引用傳回。是以,我們不難了解前面三個例子中頭兩個例子為什麼是這個答案了。


 


隻有使用引号包含文本的方式建立的String對象之間使用“+”連接配接産生的新對象才會被加入字元串池中。對于所有包含new方式建立對象(包括null)的“+”連接配接表達式,它所産生的新對象都不會被加入字元串池中,對此我們不再贅述。是以我們提倡大家用引号包含文本的方式來建立String對象以提高效率,實際上這也是我們在程式設計中常采用的。


 


棧(stack):主要儲存基本類型(或者叫内置類型)(char、byte、short、int、long、float、double、boolean)和對象的引用,資料可以共享,速度僅次于寄存器(register),快于堆。 


堆(heap):用于存儲對象