一、常量池
????????常量池:一塊在Class文件結(jié)構(gòu)中,用于存放常量的數(shù)據(jù)區(qū)域。一旦該Class被加載,該常量池將會(huì)load進(jìn)入方法區(qū)中的運(yùn)行時(shí)常量池。
????????運(yùn)行時(shí)常量池:并不常態(tài)。它具有動(dòng)態(tài)的屬性,除了預(yù)置入Class文件的常量外,它還能將運(yùn)行期產(chǎn)生的常量存儲(chǔ)其中。
????????常量池技術(shù),是為了方便快捷地創(chuàng)建某些對(duì)象而出現(xiàn)的,當(dāng)需要一個(gè)對(duì)象時(shí),就可以從常量池中取一個(gè)出來(lái)(如果池中沒(méi)有則創(chuàng)建一個(gè)),則在需要重復(fù)創(chuàng)建相等變量時(shí)節(jié)省了很多時(shí)間。

二、基本類型
????????對(duì)于int num=0的存儲(chǔ),都將是變量num和數(shù)值0開(kāi)辟一個(gè)固定內(nèi)存空間,所以才會(huì)有聲明時(shí),最大值和最小值的限制(很尬,這居然是今天才理解到)。至于存儲(chǔ)的區(qū)域,需要分以下種情況:
????????1.1、當(dāng)在方法中賦值時(shí),存儲(chǔ)在該方法的棧幀中;? ?
????????1.2、當(dāng)i為實(shí)例的成員變量時(shí),存儲(chǔ)在堆中;? ??
????????1.3、當(dāng)num為實(shí)例的靜態(tài)成員,存儲(chǔ)在方法區(qū)中;? ??
????????1.4、當(dāng)num為final常量,存儲(chǔ)在運(yùn)行時(shí)常量池中。
三、引用類型
????????Object obj = new Object(),將是變量obj和對(duì)象Object的地址引用開(kāi)辟一個(gè)固定的內(nèi)存空間,存儲(chǔ)在分情況的內(nèi)存區(qū)域中。
總結(jié):基本類型變量=數(shù)值,引用類型變量=對(duì)象地址
四、由以上總結(jié),我們能解決一下幾個(gè)面試經(jīng)常遇到的問(wèn)題。
????????3.1、java傳參什么時(shí)候值傳遞、什么時(shí)候引用傳遞呢?
? ? ????????例子如:mr.method(int myNum, Object myObj);? ? void method(int num, Object obj){}
????????????對(duì)于變量myNum,因?yàn)榛绢愋偷乃鎯?chǔ)的是數(shù)值,所以傳遞的是值;對(duì)于變量myObj,因?yàn)橐妙愋偷乃鎯?chǔ)的是地址引用,所以傳遞的是引用。
????????????至于為什么要區(qū)分這個(gè),那是因?yàn)?,如果只是?jiǎn)單的值傳遞,那么方法體內(nèi)任何對(duì)參數(shù)num的操作,均不會(huì)影響到myNum。但如果是引用從傳遞,那么變量obj將獲取到的myObj的引用地址,意味著變量myObj將Object實(shí)例對(duì)象的控制權(quán)交付給變量obj。所以,變量obj任何的操作,都將影響到暫時(shí)失去對(duì)Object對(duì)象控制權(quán)的變量myObj。
????????3.2、雙等號(hào)==的含義
????????????基本數(shù)據(jù)類型之間應(yīng)用雙等號(hào),比較的是他們的數(shù)值。
????????????引用類型之間應(yīng)用雙等號(hào),比較的是他們?cè)趦?nèi)存中的存放地址。
五、基本類型和常量池技術(shù)
????java中基本類型的包裝類的大部分都實(shí)現(xiàn)了常量池技術(shù),
? ? ? ?5.1、 其中Byte,Short,Integer,Long,Character,Boolean,這5種包裝類默認(rèn)創(chuàng)建了數(shù)值[-128,127]的相應(yīng)類型的緩存數(shù)據(jù),只有超出此范圍才會(huì)去創(chuàng)建新的對(duì)象。
? ? ? ? 5.2、兩種浮點(diǎn)數(shù)類型的包裝類Float,Double并沒(méi)有實(shí)現(xiàn)常量池技術(shù)。
? ? ? ? 5.3、Integer比較更豐富的一個(gè)例子

? ? ? ? 對(duì)結(jié)果解釋:語(yǔ)句i4 == i5 + i6,因?yàn)?這個(gè)操作符不適用于Integer對(duì)象,首先i5和i6進(jìn)行自動(dòng)拆箱操作,進(jìn)行數(shù)值相加,即i4 == 40。然后Integer對(duì)象無(wú)法與數(shù)值進(jìn)行直接比較,所以i4自動(dòng)拆箱轉(zhuǎn)為int值40,最終這條語(yǔ)句轉(zhuǎn)為40 == 40進(jìn)行數(shù)值比較。(Java自動(dòng)拆箱與裝箱傳送門)
六、String類和常量池技術(shù)
? ? ? ? 6.1、字符串何時(shí)出現(xiàn)在常量池中
? ? ????????主要使用方法有兩種:
? ? ? ? ? ? first:直接使用雙引號(hào)聲明出來(lái)的String對(duì)象會(huì)直接存儲(chǔ)在常量池中。
? ? ? ? ? ? second:如果不是用雙引號(hào)聲明的String對(duì)象,可以使用String提供的intern方法。intern 方法會(huì)從字符串常量池中查詢當(dāng)前字符串是否存在,若不存在就會(huì)將當(dāng)前字符串放入常量池中
? ? ? ? 6.1、連接表達(dá)式 +
????????(1)只有使用引號(hào)包含文本的方式創(chuàng)建的String對(duì)象之間使用“+”連接產(chǎn)生的新對(duì)象才會(huì)被加入字符串池中。
? ? ? ? (2)對(duì)于所有包含new方式新建對(duì)象(包括null)的“+”連接表達(dá)式,它所產(chǎn)生的新對(duì)象都不會(huì)被加入字符串池中。
????????6.2、String str = new String("xyz");????????**創(chuàng)建了幾個(gè)對(duì)象? **
???????????采用new關(guān)鍵字新建一個(gè)字符串對(duì)象時(shí),JVM首先在字符串池中查找有沒(méi)有"xyz"這個(gè)字符串對(duì)象,如果有,則不在池中再去創(chuàng)建"xyz"這個(gè)對(duì)象了,直接在堆中創(chuàng)建一個(gè)"xyz"字符串對(duì)象,然后將堆中的這個(gè)"xyz"對(duì)象的地址返回賦給引用str,這樣,str就指向了堆中創(chuàng)建的這個(gè)"xyz"字符串對(duì)象;如果沒(méi)有,則首先在字符串池中創(chuàng)建一個(gè)"xyz"字符串對(duì)象,然后再在堆中創(chuàng)建一個(gè)"xyz"字符串對(duì)象,然后將堆中這個(gè)"xyz"字符串對(duì)象的地址返回賦給str引用,這樣,str指向了堆中創(chuàng)建的這個(gè)"xyz"字符串對(duì)象。所以得分情況,才知道要?jiǎng)?chuàng)建幾次。
6.3、java.lang.String.intern()

? ? ? ? 對(duì)于結(jié)果是不是很驚訝。intern()只是執(zhí)行順序變了一下,結(jié)果就不一樣啦。欲知所以然,且容先生步步分析。
????????jdk1.7中定義,intern()方法只是將第一次出現(xiàn)的字符串實(shí)例的地址引用,記錄在常量池中。常量池會(huì)建立其索引,索引key代表“str01”,value代表“str1指向的對(duì)象的地址引用”。
? ? ????于是開(kāi)始分析:步驟01:根據(jù)6.1中的總結(jié),還會(huì)在常量池中創(chuàng)建三個(gè)String對(duì)象,分別是對(duì)象“str”、對(duì)象“01”。且建立其引用的索引表。同時(shí)還會(huì)在堆中創(chuàng)建對(duì)象“str”、對(duì)象“01”和對(duì)象“str01”,并將對(duì)象“str01”地址引用賦值給變量str1;
? ? ? ? ?步驟02:變量str2獲取“str01”在常量池中存儲(chǔ)的value,注意此時(shí)的引用指向常量池中”str01“對(duì)象;
? ? ? ? 步驟03:根據(jù)jdk1.7,intern()方法的定義。字符串“str01”已經(jīng)在常量池中存在,所以并不會(huì)操作。如需返回,返回值是常量池中索引表的地址引用;
? ? ? ? 步驟04:根據(jù)3.2雙等號(hào)的結(jié)論。變量str2和str1,比較的是引用。此時(shí),str1指向堆中對(duì)象“str01”,而str2指向常量池中對(duì)象“str01”.故為false;
? ? ? ? 步驟06:因?yàn)樽兞縮tr3指向的堆對(duì)象“str02”還未在常量池中出現(xiàn)過(guò)。所以,常量池會(huì)建立字符串“str02”和堆對(duì)象“str02”的引用的索引;
????????步驟07:變量str4獲取”str02“在常量池中存儲(chǔ)的value,注意此時(shí)的引用指向堆中的”str02“對(duì)象.
【溫馨提示,根據(jù)步驟,畫張對(duì)象創(chuàng)建過(guò)程圖,效果杠杠的好喲喲喲】