答案是2個,大家肯定都知道。面試中經常出現的問題,今天認真分析一下。
1、 Sting s 定義了一個變量s,沒有創建對象;
2、 = 賦值,將某個對象的引用(句柄)賦給s ,沒有創建對象;
3、 “abc” 創建一個對象;
4、 new String() 創建一個對象。
首先,總結一下java創建對象的方式:new、clone、反射、反序列化
再看一下 Stirng的構造函數
public String(String original) { int size = original.count; char[] originalValue = original.value; char[] v; if (originalValue.length > size) { // The array representing the String is bigger than the new // String itself. Perhaps this constructor is being called // in order to trim the baggage, so make a copy of the array. int off = original.offset; v = Arrays.copyOfRange(originalValue, off, off+size); } else { // The array representing the String is the same // size as the String, so no point in making a copy. v = originalValue; } this.offset = 0; this.count = size; this.value = v; }
所以,我們用了new 創建了一個對象,而“abc”是當做一個對象傳過來的,so 就是兩個了
進一步探究:
1、String s = "abc"
創建了一個對象;
2、 那麼 String a="abc" ; String b="abc" 創建了幾個對象呢??
答案還是一個;
3、那麼 String s = "ab"+"cd"; 呢???
答案是三個。
解釋:
在jvm中有一個字符串池,保存了很多String對象,可以共享。所以String a="abc" ; String b="abc" 只創建了一個對象。而"ab"+"cd" 除了"ab"、"cd"還生產了新對象"abcd"。
下面有詳細介紹,抄錄自http://www.cnblogs.com/ydpvictor/archive/2012/09/09/2677260.html,特此聲明。
在JAVA虛擬機(JVM)中存在著一個字符串池,其中保存著很多String對象,並且可以被共享使用,因此它提高了效率。由於String類是final的,它的值一經創建就不可改變,因此我們不用擔心String對象共享而帶來程序的混亂。字符串池由String類維護,我們可以調用intern()方法來訪問字符串池。
我們再回頭看看String a="abc";,這行代碼被執行的時候,JAVA虛擬機首先在字符串池中查找是否已經存在了值為"abc"的這麼一個對象,它的判斷依據是String類equals(Object obj)方法的返回值。如果有,則不再創建新的對象,直接返回已存在對象的引用;如果沒有,則先創建這個對象,然後把它加入到字符串池中,再將它的引用返回。因此,我們不難理解前面三個例子中頭兩個例子為什麼是這個答案了。
只有使用引號包含文本的方式創建的String對象之間使用“+”連接產生的新對象才會被加入字符串池中。對於所有包含new方式新建對象(包括null)的“+”連接表達式,它所產生的新對象都不會被加入字符串池中,對此我們不再贅述。因此我們提倡大家用引號包含文本的方式來創建String對象以提高效率,實際上這也是我們在編程中常采用的。
棧(stack):主要保存基本類型(或者叫內置類型)(char、byte、short、int、long、float、double、boolean)和對象的引用,數據可以共享,速度僅次於寄存器(register),快於堆。
堆(heap):用於存儲對象