今天去面試的時候碰到了這個問題:String str = new String("abc"); 創建了幾個對象,回來自己研究並查閱資料才發現答錯了。。
網上的爭論不少,有的說是兩個,答案應該是:兩個或一個
理由解釋如下:
都了解java 的字符串常量緩沖區(字符串池,字符串常量池),
如果代碼是這樣的:
- String str2 = new String("abc");
並且 abc 字符串之前沒有用過,這毫無疑問創建了兩個對象,一個是new String 創建的一個新的對象,一個是常量“abc”對象的內容創建出的一個新的String對象,
但是如果代碼是這樣子的:
- String str1 = "abc";
- String str2 = new String("abc");
嗯,創建幾個就不好說了,我們還是測試一下吧,首先我們打開cmd.exe, 通過javac *.java編譯好該Java文件,然后通過命令javap -c *來查看java編譯后的ByteCode字節碼,
ldc的含義是:將常量值從常量池中取出來並且壓入棧中。從上圖中,我們可以看到第0行和第7行中的字符串引用是同一個,這說明了,在編譯期間,該字符串變量的值已經確定了下來,並且將該字符串值緩存在緩沖區中,同時讓該變量指向該字符串值,后面如果有使用相同的字符串值,則繼續指向同一個字符串值
所以String str2 = new String("abc"); 此時就創建一個對象,而abc 則是從字符串常量緩沖區中取出來的。
ok。就是這個樣子。
String str = new String("abc"); 首先要看常量池里是否有“abc”這個字符串,如果有,則創建一個,如果沒有,則創建兩個。
我們可以把上面這行代碼分成String str、=、"abc"和new String()四部分來看待。String str只是定義了一個名為str的String類型的變量,因此它並沒有創建對象;=是對變量str進行初始化,將某個對象的引用(或者叫句柄)賦值給它,顯然也沒有創建對象;現在只剩下new String("abc")了。那么,new String("abc")為什么又能被看成"abc"和new String()呢?
我們來看一下被我們調用了的String的構造器:
public String(String original) { //other code ... } 大家都知道,我們常用的創建一個類的實例(對象)的方法有以下兩種:
一,使用new創建對象。
二、調用Class類的newInstance方法,利用反射機制創建對象。
我們正是使用new調用了String類的上面那個構造器方法創建了一個對象,並將它的引用賦值給了str變量。同時我們注意到,被調用的構造器方法接受的參數也是一個String對象,這個對象正是"abc"。由此我們又要引入另外一種創建String對象的方式的討論——引號內包含文本。