常量池和基本類型、引用類型

一、常量池

????????常量池:一塊在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ò)程圖,效果杠杠的好喲喲喲】



????????我是先生,找尋著那位迷路的Miss。最后,愿各位javaer,合上電腦的剎那,有著俠客收劍入鞘的驕傲!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • ??需要說(shuō)明的一點(diǎn)是,這篇文章是以《深入理解Java虛擬機(jī)》第二版這本書為基礎(chǔ)的,這里假設(shè)大家已經(jīng)了解了JVM的運(yùn)...
    Geeks_Liu閱讀 14,299評(píng)論 5 44
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語(yǔ)法,類相關(guān)的語(yǔ)法,內(nèi)部類的語(yǔ)法,繼承相關(guān)的語(yǔ)法,異常的語(yǔ)法,線程的語(yǔ)...
    子非魚_t_閱讀 34,878評(píng)論 18 399
  • 前言 不知道大家有沒(méi)有這樣一種感覺(jué),程序員的數(shù)量井噴了??赡苁且?yàn)榛ヂ?lián)網(wǎng)火了,也可能是各家培訓(xùn)機(jī)構(gòu)為我們拉來(lái)了大量...
    活這么大就沒(méi)飽過(guò)閱讀 2,851評(píng)論 6 25
  • 的了?一
    vicky_ls閱讀 277評(píng)論 0 0
  • 天地有正氣,周流未停息--何為本性
    念一SS閱讀 141評(píng)論 0 0

友情鏈接更多精彩內(nèi)容