Java--Integer的常量缓存池(默认-128~127数值范围)
JDK1.5之后,新增了自動拆、裝箱功能,如以前創建一個Integer對象,需要 使用 “new”關鍵字?
而現在Java中可以直接賦值如下:
Integer不是new出Integer對象,而是直接賦值,就是自動裝箱過程。
Integer a = new Integer("100");//JDK1.5之后 Integer b = 100; int x = b;再來測試如下代碼:?
/*** JDK1.5之后,新增了自動拆、裝箱功能* 緩存以支持 JLS 要求的 -128 和 127(含)之間值的自動裝箱的對象標識語義。* 緩存在第一次使用時初始化。 緩存的大小可以由 -XX:AutoBoxCacheMax=<size> 選項控制。* 在VM初始化過程中,java.lang.Integer.IntegerCache.high屬性可能會被設置并保存在sun.misc.VM類的私有系統屬性中** 1、IntegerCache 緩存范圍為 -128~127(默認范圍)* 2、大小可由 -XX:AutoBoxCacheMax調整*/ public class IntegerTest {public static void main(String[] args) {Integer i1 = 127;Integer i2 = 127;System.out.println(i1 == i2);Integer i3 = -128;Integer i4 = -128;System.out.println(i3 == i4);Integer i5 = -150;Integer i6 = -150;System.out.println(i5 == i6);Integer i7 = 130;Integer i8 = 130;System.out.println(i7 == i8);Integer i9 = new Integer("127");Integer i10 = new Integer("127");System.out.println(i9 == i10);} }輸出結果如下:
true true false false false一、Integer緩存池 IntegerCache
我們可以看下 Integer.java 類 源碼:
/*** Cache to support the object identity semantics of autoboxing for values between* -128 and 127 (inclusive) as required by JLS.** The cache is initialized on first usage. The size of the cache* may be controlled by the {@code -XX:AutoBoxCacheMax=<size>} option.* 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.*/private static class IntegerCache {static final int low = -128;static final int high;static final Integer cache[];static {// high value may be configured by propertyint h = 127;String integerCacheHighPropValue =sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");if (integerCacheHighPropValue != null) {try {int i = parseInt(integerCacheHighPropValue);i = Math.max(i, 127);// Maximum array size is Integer.MAX_VALUEh = Math.min(i, Integer.MAX_VALUE - (-low) -1);} catch( NumberFormatException nfe) {// If the property cannot be parsed into an int, ignore it.}}high = h;cache = new Integer[(high - low) + 1];int j = low;for(int k = 0; k < cache.length; k++)cache[k] = new Integer(j++);// range [-128, 127] must be interned (JLS7 5.1.7)assert IntegerCache.high >= 127;}private IntegerCache() {}}IntegerCache 方法上注釋大概意思
緩存以支持 JLS 要求的 -128 和 127(含)之間值的自動裝箱的對象標識語義。
緩存在第一次使用時初始化。 緩存的大小可以由 -XX:AutoBoxCacheMax=<size> 選項控制。
在VM初始化過程中,java.lang.Integer.IntegerCache.high屬性可能會被設置并保存在sun.misc.VM類的私有系統屬性中。
由此得到2個重點關鍵字:
1、IntegerCache 緩存范圍為?-128~127(默認范圍)
2、大小可由?-XX:AutoBoxCacheMax?調整
可以得到解釋緩存生成的范圍是-128~127,參數可以啟動之前配置JVM參數AutoBoxCacheMax進行修改
Integer類中存在一個緩沖范圍,有一個規范叫JSL(Java Language Specification,java語言規范)對Integer的緩沖做了約束,規定其范圍為:(-128-127)之間
這的IntegerCache有一個靜態的Integer數組,在類加載時就將 -128 到 127 的Integer對象創建了,并保存在cache數組中,一旦程序調用valueOf 方法,如果 變量i 的值是在-128 到 127 之間就直接在cache緩存數組中去取Integer對象。
如果超出了范圍,會從堆區new一個Integer對象來存放值
再看其它的包裝器:
Boolean:(全部緩存)
Byte:(全部緩存)
Character(<= 127緩存)
Short(-128 — 127緩存)
Long(-128 — 127緩存)
Float(沒有緩存)
Doulbe(沒有緩存)
這時,我們看下上述代碼的內存圖
1、Java中,在-128~127的Integer值并且以
Integer x = value;
的方式賦值的Integer值在進行==和equals比較時,都會返回true,因為Java里面對處在在-128~127之間的Integer值,用的是原生數據類型int,會在整數型常量內存池里,也就是說這之間的Integer值進行==比較時只是進行int原生數據類型的數值比較,而超出-128~127的范圍,進行== 比較時是進行地址及數值比較
2、如果通過??
Integer x = new Integer("127");
方式創建,還是和以前創建對象引用一樣,在堆區中創建一個對象,然后將棧中引用指向這個對象,因此 i7 和 i8兩個引用內存地址不同
注:Java中的Integer數值范圍并不是-128到127。Java中的int占用4個字節,4*8=32位,去除一個符號位,實際表示數據大小的有32-1位;而是說有一個整數常量緩存池供Integer自動裝箱時使用,提高效率。
二、IntegerCache范圍修改
1、我們在JVM運行參數上加上 -XX:AutoBoxCacheMax=200
IDEA中,在界面位置依次選擇
Run --> Eidt Configurations --> Modify options --> Add VM options
VM options 添加?-XX:AutoBoxCacheMax=200參數
添加之后就能在界面位置看到了,可以添加運行參數
Apply后 運行代碼 查看效果
public static void main(String[] args) {Integer a = 127;Integer b = 127;System.out.println(a == b);Integer c = 128;Integer d = 128;System.out.println(c == d);Integer e = 200;Integer f = 200;System.out.println(e == f);Integer g = 201;Integer h = 201;System.out.println( g == h);}?輸出結果如下:
true true true false?200時取自IntegerCache, 201則是不同指針的new Integer了。證明配置生效
2、我們在JVM運行參數上加上 -XX:AutoBoxCacheMax=120
public static void main(String[] args) {Integer a = 127;Integer b = 127;System.out.println(a == b);Integer c = 128;Integer d = 128;System.out.println(c == d);Integer e = 100;Integer f = 100;System.out.println(e == f);}輸出如下:
true false true此時緩存池的值high是120,a、b = 127時 127應該是new的 a == b 應該是false
難道配置沒生效,其實還是127?
其實不是我們設置的沒生效,通過打印high的值,我們發現配置確實是生效了的,但沒生效的原因是源碼中做了判斷。貼一段IntegerCache中為緩存池最大值賦值的方法
?
vm參數AutoBoxCacheMax的值與127做判斷,取最大值,也就是說,如果我們設置的AutoBoxCacheMax參數比127小,則不會生效?
結論:
-XX:AutoBoxCacheMax設置可以修改緩存池的最大范圍,但需要大于127才能生效,小于等于127時,依然取的是默認值127
總結
以上是生活随笔為你收集整理的Java--Integer的常量缓存池(默认-128~127数值范围)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: tp6 openid获取 JWT中间件
- 下一篇: Vue重复点击同一个路由报错问题解决