日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

常量缓存与integer比较_Integer缓存范围到底是多少?

發布時間:2025/3/12 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 常量缓存与integer比较_Integer缓存范围到底是多少? 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

本文主要大致思路為:

不管從工作中還是面試,這篇文章都應該好好看完,本人認為是非常有用的。

案例

Integer是基本類型int的封裝類。平時不管是入坑多年的小伙伴還在入坑路上的小伙伴,都應該知道的使用頻率是相當高。

下面模仿訂單支付,做了一個訂單支付狀態枚舉類PayStatusEnum

public class IntegerDemo {

public static void main(String[] args) {

Integer a = new Integer(8);

Integer b = Integer.valueOf(8);

Integer c = 8;

System.out.println(a.equals(b));

System.out.println(a.equals(c));

System.out.println(b.equals(c));

System.out.println(a == b);

System.out.println(a == c);

System.out.println(b == c);

}

}

結果輸出什么?

把上面代碼中的8改成128后,又輸出什么?

public class IntegerDemo {

public static void main(String[] args) {

Integer a = new Integer(128);

Integer b = Integer.valueOf(128);

Integer c = 128;

System.out.println(a.equals(b));

System.out.println(a.equals(c));

System.out.println(b.equals(c));

System.out.println(a == b);

System.out.println(a == c);

System.out.println(b == c);

}

}

答案慢慢道來。

解析案例

Integer整體閱覽

構造方法

private final int value;

public Integer(int value) {

this.value = value;

}

太簡單了,沒什么可講的。

valueOf()方法

public static Integer valueOf(String s) throws NumberFormatException {

return Integer.valueOf(parseInt(s, 10));

}

//@HotSpotIntrinsicCandidate 這個注解是JDK9才引入的

//HotSpot 虛擬機將對標注了@HotSpotIntrinsicCandidate注解的方法的調用,

//替換為直接使用基于特定 CPU 指令的高效實現。這些方法我們便稱之為 intrinsic。

public static Integer valueOf(int i) {

//如果i在low和high之間就使用緩存

if (i >= IntegerCache.low && i <= IntegerCache.high){

return IntegerCache.cache[i + (-IntegerCache.low)];

}

return new Integer(i);

}

上面valueOf()方法中用到了IntegerCache,下面我們來聊聊。

IntegerCache

下面是IntegerCache源碼和部分注釋:

/**

* Cache to support the object identity semantics of autoboxing for values between

* -128 and 127 (inclusive) as required by JLS.

* JLS協議要求緩存在-128到127之間(包含邊界值)

*

* The cache is initialized on first usage.

* 程序第一次使用Integer的時候

* The size of the cache may be controlled by the {@code -XX:AutoBoxCacheMax=} option.

* JVM 的啟動參數 -XX:AutoBoxCacheMax=size 修改最大值

* During VM initialization, java.lang.Integer.IntegerCache.high property

* may be set and saved in the private system properties in the

* sun.misc.VM class.

* 可以通過系統屬性來獲得:-Djava.lang.Integer.IntegerCache.high=

*/

private static class IntegerCache {

static final int low = -128;

static final int high;

//使用數組來緩存常量池

static final Integer cache[];

static {

// high value may be configured by property

//最大值是可以配置的

int h = 127;

String integerCacheHighPropValue =

sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");

//如果有配置-XX:AutoBoxCacheMax=

if (integerCacheHighPropValue != null) {

try {

int i = parseInt(integerCacheHighPropValue);

//和127進行比較,誰大用誰

i = Math.max(i, 127);

// Maximum array size is Integer.MAX_VALUE

//再比較,獲取最小值

h = Math.min(i, Integer.MAX_VALUE - (-low) -1);

} catch( NumberFormatException nfe) {

// If the property cannot be parsed into an int, ignore it.

// 如果該值配置錯誤則忽略該參數配置的值,使用默認范圍-128~127

}

}

high = h;

cache = new Integer[(high - low) + 1];

int j = low;

// 緩存通過for循環來實現,創建范圍內的整數對象并存儲到cache數組中

// 程序第一次使用Integer的時候需要一定的額外時間來初始化該緩存

for(int k = 0; k < cache.length; k++){

cache[k] = new Integer(j++);

}

//無論如何,緩存的最大值肯定是大于等于127

assert IntegerCache.high >= 127;

}

//私有的構造方法,因為所有的屬性均屬于類常量

private IntegerCache() {}

}

整個靜態塊流程:

那么,如何設置java.lang.Integer.IntegerCache.high的值呢?

The size of the cache may be controlled by the {@code -XX:AutoBoxCacheMax=} option.

注釋中已經說清楚,可以使用-XX:AutoBoxCacheMax=設置。

寫個demo來debug看看

public class IntegerDemo {

public static void main(String[] args) {

Integer a = 8;

Integer b =Integer.valueOf(8);

System.out.println(a.equals(b));

System.out.println(a == b);

}

}

設置-XX:AutoBoxCacheMax=100

開始debug

看看high的值

是127,那就對了,因為上面

設置-XX:AutoBoxCacheMax=130

開啟debug模式

注意:low=-128是不會變的,整個緩存初始化過程并沒有對low進行修改,再說low是常量。

-XX:AutoBoxCacheMax最大能設置成多大?

因為Integer的最大值是2147483647 ,所以我們這里使用這個值試試,

開始debug,直接報OOM了

為什么會OOM呢?

如果-XX:AutoBoxCacheMax沒有設置值,那么對應數組是這樣的。

equals()方法

上面的案例中有equals方法,這里把這個方法也拿出來聊聊

private final int value;

public boolean equals(Object obj) {

if (obj instanceof Integer) {

//這里比較的是兩個int類型的值

return value == ((Integer)obj).intValue();

}

//obj不是Integer類型直接返回false

return false;

}

回到上面的案例中

當我們使用equals方法比較兩個對象是否相等的時候其實就是比較他們的value值。

所以不管是128還是8,equals后肯定都是true。

當引用類型使用==進行比較的時候,此時比較的是兩個引用的對象的地址,是不是同一個。

public class IntegerDemo {

public static void main(String[] args) {

Integer a = new Integer(8);

Integer b = Integer.valueOf(8);

Integer c = 8;

System.out.println(a.equals(b));

System.out.println(a.equals(c));

System.out.println(b.equals(c));

System.out.println(a == b);

System.out.println(a == c);

System.out.println(b == c);

}

}

我們看看器class文件中的字節碼;

本地變量表

每個本地變量賦值的過程

這里我們可以得出一個結論:

Integer c =8;就是Integer c = Integer.valueOf(8);

上面Integer b = Integer.valueOf(8);,那就說明變量b和c都是使用Integer.valueOf()獲取到的。

valueOf方法中

-XX:AutoBoxCacheMax不設置

上面關于IntegerCache的low和high已經進行了說明,low永遠是-128,所以當我們沒有設置

-XX:AutoBoxCacheMax 的值的時候,這時候 high=127。

當Integer.valueOf(8);的時候,就會進入上面代碼中的if中。然后從IntegerCache中的數組cache中獲取。

但是IntegerCache中的cache數組是個常量數組。

言外之意,就是一旦給這個數組cache賦值后,就不會變了。

Integer b = Integer.valueOf(8);和Integer c=8;

b和c不就是都指向同一個引用地址嗎?

所以 b==c為true;

但是Integer b=Integer.valueOf(128);

此時就不進入if中,而是直接new一個Integer對象

所以此時

Integer b=Innteger.valueOf(128) ;和Integer c = 128;

都會各自new 一個Integer對象,

此時的b==c為false。

這里也就是網上很多文章也就說到這里,就是比較當前int i 這個i是不是在-128到127范圍之內。

-XX:AutoBoxCacheMax設置為130

如果我們把-XX:AutoBoxCacheMax設置為130。那么上面

Integer b=Innteger.valueOf(128) ;和Integer c = 128;

也會進入if條件中。

最后b==c為true。

如何避坑

Integer是基本類型int的封裝類,那么在平常使用的時候需要注意幾點:

1,如果使用Integer,注意Integer的默認是null,容易引起空指針異常NullPointerException。

2,如果使用int類型,注意int類型的初始值是0,很多設計某某狀態時,很喜歡用0作為某個狀態,這里要小心使用。

3,另外從內存使用層面來講,int是基本數據類型,只占用4個字節,Integer是一個對象,當表示一個值時Integer占用的內存空間要高于int類型,從節省內存空間考慮,建議使用int類型(建議了解一下Java對象內存布局)。

4,Integer使用的時候,直接賦值,Integer c = 8,不要new Integer(8)。因為直接賦值就是Integer.valueOf方法使用緩存,沒必要每次都new一個新對象,有效提高內存使用。

5,如果系統中大量重復的使用比127大的數,建議JVM啟動的時候為-XX:AutoBoxCacheMax=size 適當的大小,提升內存使用效率(但是也不能太大,上面我們已經演示了可能出現OOM)。

面試題

面試題1

Integer num1 = new Integer(10);

Integer num2 = new Integer(10);

System.out.println(num1.equals(num2));

System.out.println(num1 == num2);

面試題2

Integer num3 = 100;

Integer num4 = 100;

System.out.println(num3.equals(num4));

System.out.println(num3 == num4);

面試題3

Integer num5 = 1000;

Integer num6 = 1000;

System.out.println(num5.equals(num6));

System.out.println(num5 == num6);

把上面看完了,在回頭來看看這種面試題,還難嗎?

如果在面試中遇到面試題3,可以適當反問一下面試官是否有對緩存范圍進行調整,或許某些面試官都會懵逼。

赤裸裸的吊打面試官。

總結

1.引用類型的==是比較對應的引用地址。

2.Integer中使用的默認緩存是-128到127。但是可以在JVM啟動的時候進行設置。

3.Integer b=Integer.valueOf(8);和Integer b=8;是一樣的效果。

4.Integer.valueOf()方式,比較是否在緩存范圍之內,在就直接從緩存中獲取,不在new一個Integer對象。

5.每次使用new來創建Integer對象,是用不到IntegerCache緩存的。

6.Integer中的使用緩存的方式也可以理解為享元模式。

歡迎關注我的公眾號:java后端技術全棧

專業做Java相關技術分享的的公眾號。一個純粹的Java技術分享達人。

總結

以上是生活随笔為你收集整理的常量缓存与integer比较_Integer缓存范围到底是多少?的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。