Integer 緩存(IntegerCache)是 Java 5 中引入的一個有助於節省內存、提高性能的特性
廢話不多說,看一個栗子
/**
* @author :Vimonster
* @time : 2019/12/19 10:41
* @slogan: 任時間再怎樣低頭呢喃,也要不揮淚後風雨兼程
* @description:
*
* 關於Integer 和 int 的一些注意事項
*
*/
public class IntegerBug {
public static void main(String[] args) {
test1();
test2();
}
/**
* 比較值問題
*
*/
private static void test1(){
Integer a = 110;
int b = 110;
Integer c = new Integer(110);
System.out.println(a == b); //true 此處相等 應爲Integer在和int比較時會自動拆箱 變爲int 此處a自動拆箱爲int類型 對象的比較也就變成了值的比較
System.out.println(a == c); //false 因爲c使用了new對象 c的值其實在堆空間 而 a 的值在常量池 兩個都是對象 對象地址不一樣 所以是false
}
/**
*
* -128與127之間,Integer會自動存在IntegerCache.cache 直接從內存中去取,不在這個範圍則會new新對象
*
*/
private static void test2(){
int a = 127;
int b = 127;
Integer c = 127; //編譯的時候 翻譯爲:Integer c = Integer.valueOf(127);
Integer d = new Integer(127);
Integer e = 127;
System.out.println(a == b); //true
System.out.println(a == c); //true
System.out.println(c == d); //false
System.out.println(a == d); //true
System.out.println(c == e); //true c 和 e 實際上是同一個對象。所以使用”==“比較返回true。
test3();
}
private static void test3(){
int a = 128;
int b = 128;
Integer c = 128;
Integer d = new Integer(128);
Integer e = 128;
System.out.println(a == b); //true
System.out.println(a == c); //true
System.out.println(c == d); //false
System.out.println(a == d); //true
//todo 注意 java6之後如果不修改 XX:AutoBoxCacheMax=size 此處是false
// 如果修改 XX:AutoBoxCacheMax=size 使其size大於128此處就爲true
// !!!java6之後 IntegerCache.high 可以修改 !!!java6之後 IntegerCache.high 可以修改 !!!java6之後 IntegerCache.high 可以修改
System.out.println(c == e); //false //128超出了Integer緩存範圍 c 和 e 都是new 出來的對象
}
}
java6之後在不通過JVM啓動參數修改IntegerCache值的範圍的前提下,處於節省內存的考慮,JVM會緩存-128到127的Integer對象 即:IntegerCache.low=-128 IntegerCache.high=127,也就是在IntegerCache=[-128, 127]
- 自動裝箱:
將一個int賦值給一個Integer,會發生自動裝箱,裝箱過程系統對int類型的值X執行了Integer.valueOf(X);
Integer a = 10;
//在編譯時 上述代碼被翻譯爲下面的代碼
//10在[-128, 127]範圍內所以直接從緩存池返回10對應的Intger對象,否則將會new一個新的Integer賦值給a
Integer a = Integer.valueof(10);
- 自動拆箱:
一個Integer對象和一個int值作比較,會發生自動拆箱,拆箱過程系統對Integer類型的對象X執行了X.intValue();
Integer a = 110;
int b = 110;
//在Integer對象a 和 基本類型 b 做比較時 a 會做這樣的轉化 a = a.intValue(); 變成一個int類型的值
// 再和b做比較 此時變成了數值之間的比較
System.out.println(a == b);
回頭再看test1方法
Integer a = 110;
這一行簡單的代碼,其實發生了很多事。 110是基本類型 賦值 給一個Intger類型的對象 a ,其實在編譯過程中,由於自動裝箱, 這行代碼會翻譯成 如下:
Integer c = Integer.valueOf(110);
我們看一下jdk1.8的Integer.valueOf(x)的源碼
/**
*
* 將基本類型int 處理完後 返回Integer對象的過程叫做自動裝箱
*/
public static Integer valueOf(int i) {
//判斷int類型的值i 是否介於Integer緩存池的最大值和最小值之間
if (i >= IntegerCache.low && i <= IntegerCache.high)
//如果i在Integer緩存池的範圍 直接從緩存池拿裝箱後的對象
return IntegerCache.cache[i + (-IntegerCache.low)];
//如果i不在緩存池範圍內 new一個新的對象返回
return new Integer(i);
}
知道了上述源碼後,再來看test3方法中的 c == e 爲什麼返回是false了
Integer c = 128; // c不在[-128, 127]範圍內 根據上述源碼得知裝箱過程中 c = new Integer(128);
Integer e = 128; // e不在[-128, 127]範圍內 根據上述源碼得知裝箱過程中 e = new Integer(128);
//c是一個new 出來的對象 e是也是一個new出來的對象 在堆內存中對應的是兩個對象 所以此處爲false
System.out.println(c == e); //false
- 如何修改IntegerCache的範圍
都說Integer緩存池的大小在-128和127之間,也就是IntegerCache.low=-128 IntegerCache.high=127
嚴格來說應該是如果自己不指定緩存值的範圍, 默認的是這樣, 什麼緩存池的範圍還可以自己指定???
是的, 你沒聽錯,在java6之後, 可以使用JVM的啓動參數設置最大值 (通過JVM的啓動參數
-XX:AutoBoxCacheMax=size 進行修改)
不信我用idea來演示一下,idea修改JVM啓動參數
1.idea右上角如圖中所示 點擊一下有個下拉框 點擊Edit Configurations..選項 彈出框如圖二所示
2.在該頁面的VM options選項中填寫-XX:AutoBoxCacheMax=256 設置Integer緩存值最大值爲256
此時再次運行上面的test3 你會發現 c == e 會變成true 因爲此處的128在新設置的Integer緩存池-128~256範圍之內,所以在進行裝箱操作的時候,是直接從Integer緩存池中拿的對象, c和e都是從緩存池中拿的同一個對象, 所以c == e 是true
private static void test3(){
int a = 128;
int b = 128;
Integer c = 128;
Integer d = new Integer(128);
Integer e = 128;
System.out.println(a == b); //true
System.out.println(a == c); //true
System.out.println(c == d); //false
System.out.println(a == d); //true
//todo 注意 java6之後如果不修改 XX:AutoBoxCacheMax=size 此處是false
// 如果修改 XX:AutoBoxCacheMax=size 使其size大於128此處就爲true
// !!!java6之後 IntegerCache.high 可以修改 !!!java6之後 IntegerCache.high 可以修改 !!!java6之後 IntegerCache.high 可以修改
System.out.println(c == e); //true//128未超出了Integer新設置的最大緩存256 c 和 e 是同一個對象 是直接從緩存池中拿到的對象
}
所以從嚴格意義上來說 在java6之後, 在不通過JVM啓動參數修改Integer緩存池的範圍值時, 系統的Integer緩存池的大小纔是在-128和127之間。
上述就是Integer和int之間作比較常見的一些問題嘍 !!!
如果覺得生活很迷茫,就只管埋頭變強、
2019-12-19 --於南京