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

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

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

一. Integer底層原理探究

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

除了要掌握Integer的用法之外,我們還要了解它的一些底層內容,因為在面試時,關于Integer的底層考察的比較多。比如一個常見的面試題是這樣的:請問int和Integer的區(qū)別有哪些?

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

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

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

2. 被final修飾的Integer類

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

從源碼中可以看出,Integer是Number的一個子類,且被final所修飾!請大家回顧一些之前講過的final知識點。

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

3. IntegerCache緩沖區(qū)

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

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

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

4. 幾個核心實驗

為了能夠講清楚Integer的底層邏輯,小編給大家設計了如下代碼,用于驗證Integer的底層設計。

4.1 比較new出的兩個Integer對象

我們通過new對象的方式,來創(chuàng)建兩個Integer對象i和j,并比較這兩個對象。

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

從運行的結果中可以看出,通過new生成的兩個Integer對象永遠是不會相等的。這是因為new生成的是兩個對象,Integer變量實際上是對Integer對象的引用,這兩個對象的內存地址是不同的。

4.2 Integer對象和int變量進行比較

接下來我們在把一個Integer對象和int變量進行比較,如下:

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

Integer變量和int變量進行比較時,只要兩個變量的值是相等的,結果就為true。這是因為Integer包裝類和int基本類型進行比較時,Java會進行自動拆箱操作,將Integer轉為了int,然后再進行比較,實際上就變?yōu)榱藘蓚€int變量的比較。本案例中兩者的值都是100,所以用“==”等號進行比較時自然就是相等的。

4.3 非new的Integer變量和new出的Integer變量進行比較

然后我們再把一個非new的Integer變量和new出的Integer變量進行比較,如下所示:

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

在這段代碼中,非new生成的Integer變量和new Integer()生成的變量進行比較時,結果卻為false 這是因為非new生成Integer變量時,內部會調用valueOf()方法,進行自動裝箱操作,此時會把Integer變量的值指向Java常量池中的數(shù)據(jù)。而new Integer()生成的變量,則指向的是堆中新建的對象,兩者在內存中的地址是不同的。

4.4 兩個非new生成的Integer對象進行比較

接著我們再對兩個非new生成的Integer對象進行比較,如下所示:

//兩個非new生成的Integer對象進行比較
//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

這段代碼中,兩個非new生成的Integer對象進行比較時,如果兩個變量的取值在 -128到127 之間,則比較結果為true;如果兩個變量的值不在此區(qū)間,則比較結果為false。 這又是為什么呢? 其實要想弄明白這個原因,我們只需要看看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值自動裝箱變成對應的Integer實例。 并且從這段源碼中我們可以看到其內部有一個if判斷,根據(jù)判斷結果的不同,會有2種不同的方式得到Integer對象:當arg大于等于-128且小于等于127時,則直接從緩存中返回一個已經存在的對象;如果參數(shù)的值不在這個范圍內,則new一個Integer對象返回,要么new Integer,要么從int常量池中獲取 !

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

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

最后我們再做一個實驗,來看看==與equals比較兩個Integer對象時有什么不同。

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

從該實驗中可以看出,==比較時,較小的兩個相同的Integer會返回true,較大的兩個相同的Integer會返回false。結合上面給大家的講解,你思考一下這是為什么?

5. 結論

通過以上的幾個核心實驗,可以給大家梳理出一個結論:

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

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

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

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

實際上,方法2和方法3的本質是一樣的,所以開發(fā)時為了簡潔,我們一般是通過方法3來得到一個Integer對象。但是盡量不要使用方法1來構建Integer對象,這是因為方法1總是會創(chuàng)建一個新的 Integer 實例,而方法2和方法3則會盡可能地返回緩存的實例對象,以節(jié)省內存。

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

二. 結語

最后我再梳理一下該問題的回答要點:

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

然后簡介基本類型與包裝類,最后還能說明為什么需要有包裝類;

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

最后再說int與Integer的深入區(qū)別,即底層的源碼和原理。

如果你可以把我總結的這4點都能回答好,就這一個問題,面試官就會對你留下深刻的影響,他就會認為你的基礎知識足夠扎實,因為大多數(shù)人只會回答int和Integer的基本區(qū)別,很少有人去回答底層的內容!而通過這個問題,面試官也會了解到,你對Java的內存分配是很熟悉的!

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

相關文章

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

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

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

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

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

    一文搞懂MyBatis一級緩存和二級緩存

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

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

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

    java調用process線程阻塞問題的解決

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

    Springboot中使用緩存的示例代碼

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

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

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

    java虛擬機學習筆記進階篇

    在本篇內容里小編給大家分享了關于java虛擬機學習筆記的進階內容,需要的朋友們跟著學習下。
    2019-06-06
  • 寧可用Lombok也不把成員設置為public原理解析

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

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

    Java中stream的用法詳細解讀

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

最新評論