欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

探究Java中Integer緩沖區(qū)底層原理

 更新時(shí)間:2023年05月09日 10:01:20   作者:一一哥Sun  
本文將會(huì)給大家講一講Integer這個(gè)包裝類的底層原理。在現(xiàn)在的就業(yè)環(huán)境下,我們需要知其然,還要知其所以然,才能更好地滿足就業(yè)需求,感興趣的小伙伴可以參考閱讀

一. Integer底層原理探究

1. int和Integer的區(qū)別

除了要掌握Integer的用法之外,我們還要了解它的一些底層內(nèi)容,因?yàn)樵诿嬖嚂r(shí),關(guān)于Integer的底層考察的比較多。比如一個(gè)常見的面試題是這樣的:請(qǐng)問(wèn)int和Integer的區(qū)別有哪些?

面對(duì)這樣的一道題目,你該怎么回答?常規(guī)的答案其實(shí)很容易答出來(lái),比如:

  • int是基本數(shù)據(jù)類型,代表整型數(shù)據(jù),默認(rèn)值是0;
  • Integer是 int的包裝類,屬于引用類型,默認(rèn)值為 null ;
  • int 和 Integer 都可以表示某一個(gè)整型數(shù)值;
  • Integer變量實(shí)際是對(duì)象的引用,當(dāng)new一個(gè)Integer時(shí),實(shí)際上是生成一個(gè)指針指向此對(duì)象;而int則是直接存儲(chǔ)數(shù)據(jù)值;
  • Integer可以區(qū)分出未賦值和值為 0 的區(qū)別,而int 則無(wú)法表達(dá)出未賦值的情況;
  • int 和 Integer 不能夠互用,因?yàn)樗麄兪莾煞N不同的數(shù)據(jù)類型;
  • int在初始化時(shí),可以直接寫成 int=1 的形式;
  • 因?yàn)镮nteger是包裝類型,使用時(shí)可以采用 Integer i = new Integer(1) 的形式,但因?yàn)镴ava中的自動(dòng)裝箱和拆箱機(jī)制,使得對(duì)Integer類的賦值也可以使用 Integer i= 1 的形式;
  • 如果我們只是進(jìn)行一些加減乘除的運(yùn)算 或者 作為參數(shù)進(jìn)行傳遞,那么就可以直接使用int這樣的基本數(shù)據(jù)類型;但如果想按照對(duì)象來(lái)進(jìn)行操作處理,那么就要使用Integer來(lái)聲明一個(gè)對(duì)象。

但是如果你只能回答出這樣的答案,你在面試官的眼里只能算合格,還算不上優(yōu)秀,我們需要對(duì)Integer了解地更多一些。

2. 被final修飾的Integer類

為了搞清楚Integer的底層,我們就不得不研究一下它的源碼,我們來(lái)追蹤一下Integer源碼,如下圖所示:

從源碼中可以看出,Integer是Number的一個(gè)子類,且被final所修飾!請(qǐng)大家回顧一些之前講過(guò)的final知識(shí)點(diǎn)。

我們知道,被final修飾的類是常量類,該類不能被繼承,里面的方法不能被重寫,創(chuàng)建出的對(duì)象也不能被修改!總之,Integer符合final類的特征。

3. IntegerCache緩沖區(qū)

我們還記得,在Integer中有一個(gè)valueOf()方法,該方法可以將int值轉(zhuǎn)為Integer對(duì)象。接下來(lái)我們來(lái)看看該方法的實(shí)現(xiàn)源碼,如下圖所示:

從上圖的源碼截圖中我們可以看到,Integer中有一個(gè)緩沖區(qū)叫做IntegerCache,這是Integer中的一個(gè)內(nèi)部類,如下圖所示:

我們可以看到,low就是-128,high等于127,這是緩沖區(qū)的最低和最高邊界。那么這個(gè)緩沖區(qū)的存在到底有什么用呢?大家別著急,我們先做幾個(gè)核心實(shí)驗(yàn)。

4. 幾個(gè)核心實(shí)驗(yàn)

為了能夠講清楚Integer的底層邏輯,小編給大家設(shè)計(jì)了如下代碼,用于驗(yàn)證Integer的底層設(shè)計(jì)。

4.1 比較new出的兩個(gè)Integer對(duì)象

我們通過(guò)new對(duì)象的方式,來(lái)創(chuàng)建兩個(gè)Integer對(duì)象i和j,并比較這兩個(gè)對(duì)象。

//通過(guò)new生成的兩個(gè)Integer變量進(jìn)行比較,結(jié)果為false
Integer i = new Integer(100);
Integer j = new Integer(100);
System.out.print(i == j); //false

從運(yùn)行的結(jié)果中可以看出,通過(guò)new生成的兩個(gè)Integer對(duì)象永遠(yuǎn)是不會(huì)相等的。這是因?yàn)閚ew生成的是兩個(gè)對(duì)象,Integer變量實(shí)際上是對(duì)Integer對(duì)象的引用,這兩個(gè)對(duì)象的內(nèi)存地址是不同的。

4.2 Integer對(duì)象和int變量進(jìn)行比較

接下來(lái)我們?cè)诎岩粋€(gè)Integer對(duì)象和int變量進(jìn)行比較,如下:

Integer i = new Integer(100);
int j = 100;
System.out.print(i == j); //true

Integer變量和int變量進(jìn)行比較時(shí),只要兩個(gè)變量的值是相等的,結(jié)果就為true。這是因?yàn)镮nteger包裝類和int基本類型進(jìn)行比較時(shí),Java會(huì)進(jìn)行自動(dòng)拆箱操作,將Integer轉(zhuǎn)為了int,然后再進(jìn)行比較,實(shí)際上就變?yōu)榱藘蓚€(gè)int變量的比較。本案例中兩者的值都是100,所以用“==”等號(hào)進(jìn)行比較時(shí)自然就是相等的。

4.3 非new的Integer變量和new出的Integer變量進(jìn)行比較

然后我們?cè)侔岩粋€(gè)非new的Integer變量和new出的Integer變量進(jìn)行比較,如下所示:

//非new生成的Integer變量和new Integer()生成的變量進(jìn)行比較
Integer i = new Integer(100);
//自動(dòng)裝箱
Integer j = 100;
System.out.print(i == j); //false

在這段代碼中,非new生成的Integer變量和new Integer()生成的變量進(jìn)行比較時(shí),結(jié)果卻為false 這是因?yàn)榉莕ew生成Integer變量時(shí),內(nèi)部會(huì)調(diào)用valueOf()方法,進(jìn)行自動(dòng)裝箱操作,此時(shí)會(huì)把Integer變量的值指向Java常量池中的數(shù)據(jù)。而new Integer()生成的變量,則指向的是堆中新建的對(duì)象,兩者在內(nèi)存中的地址是不同的。

4.4 兩個(gè)非new生成的Integer對(duì)象進(jìn)行比較

接著我們?cè)賹?duì)兩個(gè)非new生成的Integer對(duì)象進(jìn)行比較,如下所示:

//兩個(gè)非new生成的Integer對(duì)象進(jìn)行比較
//i與j的取值范圍是在 -128~127 之間!
Integer i = 100;
Integer j = 100;
System.out.print(i == j); //true

//x與y的取值范圍不在 -128~127 之間!
Integer x = 200;
Integer y = 200;
System.out.print(x == y); //false

這段代碼中,兩個(gè)非new生成的Integer對(duì)象進(jìn)行比較時(shí),如果兩個(gè)變量的取值在 -128到127 之間,則比較結(jié)果為true;如果兩個(gè)變量的值不在此區(qū)間,則比較結(jié)果為false。 這又是為什么呢? 其實(shí)要想弄明白這個(gè)原因,我們只需要看看Integer類的valueOf()方法是怎么寫的就可以了。valueOf()方法源碼如下:

public static Integer valueOf(int i) {
    if (i >= IntegerCache.low && i <= IntegerCache.high)
        return IntegerCache.cache[i + (-IntegerCache.low)];
    return new Integer(i);
}

我們知道,valueOf(int i)方法可以將int值自動(dòng)裝箱變成對(duì)應(yīng)的Integer實(shí)例。 并且從這段源碼中我們可以看到其內(nèi)部有一個(gè)if判斷,根據(jù)判斷結(jié)果的不同,會(huì)有2種不同的方式得到Integer對(duì)象:當(dāng)arg大于等于-128且小于等于127時(shí),則直接從緩存中返回一個(gè)已經(jīng)存在的對(duì)象;如果參數(shù)的值不在這個(gè)范圍內(nèi),則new一個(gè)Integer對(duì)象返回,要么new Integer,要么從int常量池中獲取 !

之前我們構(gòu)建Integer對(duì)象的傳統(tǒng)方式是直接 new 一個(gè)Integer對(duì)象,內(nèi)部會(huì)調(diào)用構(gòu)造器。但是根據(jù)實(shí)踐,我們發(fā)現(xiàn)大部分的數(shù)據(jù)操作都是集中在有限的、較小的數(shù)值范圍內(nèi)。因而在JDK 1.5中,新增了一個(gè)靜態(tài)工廠方法valueOf(int i)。當(dāng)我們進(jìn)行Integer i=xxx 賦值操作時(shí),Java內(nèi)部會(huì)調(diào)用執(zhí)行這個(gè)valueOf()實(shí)現(xiàn)自動(dòng)裝箱。而在調(diào)用valueOf()方法時(shí),其內(nèi)部會(huì)利用緩存機(jī)制,對(duì)取值在-128~127之間的int值進(jìn)行緩存操作,這是在JDK 1.5 之后進(jìn)行的一個(gè)可以明顯改善性能的提升 。 而按照J(rèn)avadoc文檔,該緩存機(jī)制默認(rèn)會(huì)緩存在 -128 到 127 之間的值,不在該區(qū)間的值并不會(huì)進(jìn)行緩存。所以,給Integer i賦值的大小不同,比較的結(jié)果也可能會(huì)不同。

4.5 ==和equals的區(qū)別

最后我們?cè)僮鲆粋€(gè)實(shí)驗(yàn),來(lái)看看==與equals比較兩個(gè)Integer對(duì)象時(shí)有什么不同。

Integer x = 127;
Integer y = 127;

Integer m = 100000;
Integer n = 100000;

System.out.println("x == y: " + (x==y)); // true
System.out.println("m == n: " + (m==n)); // false

System.out.println("x.equals(y): " + x.equals(y)); // true
System.out.println("m.equals(n): " + m.equals(n)); // true

從該實(shí)驗(yàn)中可以看出,==比較時(shí),較小的兩個(gè)相同的Integer會(huì)返回true,較大的兩個(gè)相同的Integer會(huì)返回false。結(jié)合上面給大家的講解,你思考一下這是為什么?

5. 結(jié)論

通過(guò)以上的幾個(gè)核心實(shí)驗(yàn),可以給大家梳理出一個(gè)結(jié)論:

當(dāng)我們利用”==“等號(hào)比較兩個(gè)Integer i 和 Integer j的值時(shí),如果取值范圍是在-128~127之間,兩個(gè)相同的Integer值會(huì)返回true;如果不在該區(qū)間,兩個(gè)相同的Integer值會(huì)返回false。這是因?yàn)镮nteger是final類,編譯器把Integer i = 100; 自動(dòng)變?yōu)镮nteger i = Integer.valueOf(100); 。為了節(jié)省內(nèi)存, Integer.valueOf() 對(duì)于較小的數(shù),始終會(huì)返回相同的實(shí)例對(duì)象,因此,==比較的結(jié)果就是true。

那么如果我們只是為了比較兩個(gè)Integer對(duì)象的值是否相等,而不是為了比較兩個(gè)對(duì)象的地址是否相同,在開發(fā)時(shí)請(qǐng)盡量使用equals()方法,而不是==!

并且我們現(xiàn)在還知道,在Java中有3種方式可以構(gòu)造出一個(gè)Integer對(duì)象,代碼如下:

//方法1:
Integer i = new Integer(100);
//方法2:
Integer i = Integer.valueOf(100);
//方法3:
Integer i = 100;

實(shí)際上,方法2和方法3的本質(zhì)是一樣的,所以開發(fā)時(shí)為了簡(jiǎn)潔,我們一般是通過(guò)方法3來(lái)得到一個(gè)Integer對(duì)象。但是盡量不要使用方法1來(lái)構(gòu)建Integer對(duì)象,這是因?yàn)榉椒?總是會(huì)創(chuàng)建一個(gè)新的 Integer 實(shí)例,而方法2和方法3則會(huì)盡可能地返回緩存的實(shí)例對(duì)象,以節(jié)省內(nèi)存。

所以最終關(guān)于”int和Integer的區(qū)別有哪些“這道面試題的答案,如果你想拿到高分,就需要把Integer的底層原理也回答出來(lái)才行!如果你可以把以上內(nèi)容都回答清楚,我相信單憑這一道題目,就足以讓面試官對(duì)你刮目相看!

二. 結(jié)語(yǔ)

最后我再梳理一下該問(wèn)題的回答要點(diǎn):

先簡(jiǎn)單回顧Java中的數(shù)據(jù)類型及取值范圍;

然后簡(jiǎn)介基本類型與包裝類,最后還能說(shuō)明為什么需要有包裝類;

接著說(shuō)一下int與Integer的基本區(qū)別;

最后再說(shuō)int與Integer的深入?yún)^(qū)別,即底層的源碼和原理。

如果你可以把我總結(jié)的這4點(diǎn)都能回答好,就這一個(gè)問(wèn)題,面試官就會(huì)對(duì)你留下深刻的影響,他就會(huì)認(rèn)為你的基礎(chǔ)知識(shí)足夠扎實(shí),因?yàn)榇蠖鄶?shù)人只會(huì)回答int和Integer的基本區(qū)別,很少有人去回答底層的內(nèi)容!而通過(guò)這個(gè)問(wèn)題,面試官也會(huì)了解到,你對(duì)Java的內(nèi)存分配是很熟悉的!

以上就是探究Java中Integer緩沖區(qū)底層原理的詳細(xì)內(nèi)容,更多關(guān)于Java Integer底層原理的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Java虛擬機(jī)JVM類加載機(jī)制(從類文件到虛擬機(jī))

    Java虛擬機(jī)JVM類加載機(jī)制(從類文件到虛擬機(jī))

    所謂的類加載機(jī)制就是虛擬機(jī)將class文件加載到內(nèi)存,并對(duì)數(shù)據(jù)進(jìn)行驗(yàn)證,轉(zhuǎn)換解析和初始化,形成虛擬機(jī)可以直接使用的java類型,本文給大家介紹類加載機(jī)制過(guò)程從類文件到虛擬機(jī)的詳細(xì)說(shuō)明,感興趣的朋友跟隨小編一起看看吧
    2021-06-06
  • Java Json字符串的雙引號(hào)(

    Java Json字符串的雙引號(hào)("")括號(hào)如何去掉

    這篇文章主要介紹了Java Json字符串的雙引號(hào)("")括號(hào)如何去掉?具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-09-09
  • 一文搞懂MyBatis一級(jí)緩存和二級(jí)緩存

    一文搞懂MyBatis一級(jí)緩存和二級(jí)緩存

    本文主要介紹了一文搞懂MyBatis一級(jí)緩存和二級(jí)緩存,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-05-05
  • Linux中Java開發(fā)常用軟件安裝方法總結(jié)

    Linux中Java開發(fā)常用軟件安裝方法總結(jié)

    這篇文章主要介紹了Linux中Java開發(fā)常用軟件安裝方法總結(jié),需要的朋友可以參考下
    2020-02-02
  • java調(diào)用process線程阻塞問(wèn)題的解決

    java調(diào)用process線程阻塞問(wèn)題的解決

    這篇文章主要介紹了java調(diào)用process線程阻塞問(wèn)題的解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-06-06
  • Springboot中使用緩存的示例代碼

    Springboot中使用緩存的示例代碼

    這篇文章主要介紹了Springboot中使用緩存的示例代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-09-09
  • java?zxing合成復(fù)雜二維碼圖片示例詳解

    java?zxing合成復(fù)雜二維碼圖片示例詳解

    這篇文章主要為大家介紹了java?zxing合成復(fù)雜二維碼圖片示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-05-05
  • java虛擬機(jī)學(xué)習(xí)筆記進(jìn)階篇

    java虛擬機(jī)學(xué)習(xí)筆記進(jìn)階篇

    在本篇內(nèi)容里小編給大家分享了關(guān)于java虛擬機(jī)學(xué)習(xí)筆記的進(jìn)階內(nèi)容,需要的朋友們跟著學(xué)習(xí)下。
    2019-06-06
  • 寧可用Lombok也不把成員設(shè)置為public原理解析

    寧可用Lombok也不把成員設(shè)置為public原理解析

    這篇文章主要為大家介紹了寧可用Lombok也不把成員設(shè)置為public原理解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-03-03
  • Java中stream的用法詳細(xì)解讀

    Java中stream的用法詳細(xì)解讀

    這篇文章主要介紹了Java中stream的用法詳細(xì)解讀,Stream 是 Java8 中處理集合的關(guān)鍵抽象概念,它可以指定你希望對(duì)集合進(jìn)行的操作,可以執(zhí)行非常復(fù)雜的查找、過(guò)濾和映射數(shù)據(jù)等操作,使用Stream API 對(duì)集合數(shù)據(jù)進(jìn)行操作,就類似于使用SQL執(zhí)行的數(shù)據(jù)庫(kù)查詢,需要的朋友可以參考下
    2023-10-10

最新評(píng)論