摘要:整型對象在內部實現中通過使用相同的對象引用實現了緩存和重用。這種緩存策略僅在自動裝箱的時候有用,使用構造器創建的對象不能被緩存。行的結果為而行則為。所以行的結果為而行為。中其他類似的緩存的緩存上限可以通過虛擬機參數修改,的緩存則沒法修改。
Java5為Integer的操作引入了一個新的特性,用來節省內存和提高性能。整型對象在內部實現中通過使用相同的對象引用實現了緩存和重用。
上面的規則默認適用于整數區間 -128 到 +127(這個整數區間可以通過啟動應用的虛擬機參數修改:-XX:AutoBoxCacheMax)。這種Integer緩存策略僅在自動裝箱(autoboxing)的時候有用,使用構造器創建的Integer對象不能被緩存。Java 編譯器把原始類型自動轉換為封裝類的過程稱為自動裝箱(autoboxing),這相當于調用 valueOf 方法。
public static Integer valueOf(int i) { if (i >= IntegerCache.low && i <= IntegerCache.high) return IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer(i); }
首先看代碼:
public class TestInteger { public static void main(String[] args) { int i = 128; Integer i2 = 128; Integer i3 = new Integer(128); //Integer會自動拆箱為int,所以為true System.out.println(i == i2); System.out.println(i == i3); System.out.println("**************"); Integer i5 = 127;//java在編譯的時候,被翻譯成-> Integer i5 = Integer.valueOf(127); Integer i6 = 127; System.out.println(i5 == i6);//true Integer i9 = 128; Integer i10 = 128; System.out.println(i9 == i10);//false Integer ii5 = new Integer(127); System.out.println(i5 == ii5); //false Integer i7 = new Integer(128); Integer i8 = new Integer(123); System.out.println(i7 == i8); //false } }
首先,7行和8行輸出結果都為true,因為Integer和int比都會自動拆箱(jdk1.5以上)。
12行的結果為true,而15行則為false。java在編譯Integer i5 = 127的時候,被翻譯成-> Integer i5 = Integer.valueOf(127);所以關鍵就是看valueOf()函數了。只要看看valueOf()函數的源碼就會明白了。JDK源碼的 valueOf函數式這樣的:
public static Integer valueOf(int i) { assert IntegerCache.high >= 127; if (i >= IntegerCache.low && i <= IntegerCache.high) return IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer(i); }
看一下源碼大家都會明白,對于-128到127之間的數,會進行緩存,Integer i5 = 127時,會將127進行緩存,下次再寫Integer i6 = 127時,就會直接從緩存中取,就不會new了。所以12行的結果為true,而15行為false。
對于17行和20行,因為對象不一樣,所以為false。
對于以上的情況總結如下:
無論如何,Integer與new Integer不會相等。不會經歷拆箱過程,i3的引用指向堆,而i4指向專門存放他的內存(常量池),他們的內存地址不一樣,所以為false
兩個都是非new出來的Integer,如果數在-128到127之間,則是true,否則為false。java在編譯Integer i2 = 128的時候,被翻譯成-> Integer i2 = Integer.valueOf(128);而valueOf()函數會對-128到127之間的數進行緩存
兩個都是new出來的,都為false
int和Integer(無論new否)比,都為true,因為會把Integer自動拆箱為int再去比
AutoBoxCacheMax參數// IntegerCache,Integer類的內部類,注意它的屬性都是定義為static final private static class IntegerCache { //緩存的下界,-128,不可變 static final int low = -128; //緩存上界,暫為null static final int high; //緩存的整型數組 static final Integer cache[]; static { // 緩存上界,可以通過JVM參數來配置 int h = 127; String integerCacheHighPropValue = sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high"); if (integerCacheHighPropValue != null) { int i = parseInt(integerCacheHighPropValue); i = Math.max(i, 127); //最大的數組值是Integer.MAX_VALUE h = Math.min(i, Integer.MAX_VALUE - (-low)); } high = h; cache = new Integer[(high - low) + 1]; int j = low; for (int k = 0; k < cache.length; k++) cache[k] = new Integer(j++); } private IntegerCache() { } }
-XX:AutoBoxCacheMax這個參數是設置Integer緩存上限的參數,在VM初始化期間java.lang.Integer.IntegerCache.high屬性可以被設置和保存在私有的系統屬性sun.misc.VM class中。理論上講,當系統需要頻繁使用Integer時,或者說堆內存中存在大量的Integer對象時,可以考慮提高Integer緩存上限,避免JVM重復創造對象,提高內存的使用率,減少GC的頻率,從而提高系統的性能。
理論歸理論,這個參數能否提高系統系統關鍵還是要看堆中Integer對象到底有多少、以及Integer的創建的方式。如果堆中的Integer對象很少,重新設置這個參數并不會提高系統的性能。即使堆中存在大量的Integer對象,也要看Integer對象時如何產生的。
大部分Integer對象通過Integer.valueOf()產生。說明代碼里存在大量的拆箱與裝箱操作。這時候設置這個參數會系統性能有所提高。
大部分Integer對象通過反射,new產生。這時候Integer對象的產生大部分不會走valueOf()方法,所以設置這個參數也是無濟于事。
JDK中其他類似的緩存Integer的緩存上限可以通過Java虛擬機參數修改,Byte、Short、Long、Character的緩存則沒法修改。
Byte
private static class ByteCache { private ByteCache(){} static final Byte cache[] = new Byte[-(-128) + 127 + 1]; static { for(int i = 0; i < cache.length; i++) cache[i] = new Byte((byte)(i - 128)); } } public static Byte valueOf(byte b) { final int offset = 128; return ByteCache.cache[(int)b + offset]; }
Short
private static class ShortCache { private ShortCache(){} static final Short cache[] = new Short[-(-128) + 127 + 1]; static { for(int i = 0; i < cache.length; i++) cache[i] = new Short((short)(i - 128)); } } public static Short valueOf(short s) { final int offset = 128; int sAsInt = s; if (sAsInt >= -128 && sAsInt <= 127) { // must cache return ShortCache.cache[sAsInt + offset]; } return new Short(s); }
Long
private static class LongCache { private LongCache(){} static final Long cache[] = new Long[-(-128) + 127 + 1]; static { for(int i = 0; i < cache.length; i++) cache[i] = new Long(i - 128); } } public static Long valueOf(long l) { final int offset = 128; if (l >= -128 && l <= 127) { // will cache return LongCache.cache[(int)l + offset]; } return new Long(l); }
Character
private static class CharacterCache { private CharacterCache(){} static final Character cache[] = new Character[127 + 1]; static { for (int i = 0; i < cache.length; i++) cache[i] = new Character((char)i); } } public static Character valueOf(char c) { if (c <= 127) { // must cache return CharacterCache.cache[(int)c]; } return new Character(c); }
示例:
public class AllCacheDemo { /** * 演示JDK內部緩存 */ public static void main(String[] args) { Integer a = 28; Integer b = 28; println(a == b); Byte c = 25; Byte d = 25; println(c==d); Short p=12; Short q=12; println(p==q); Long x=127L; Long y=127L; println(x==y); Character m="M"; Character n="M"; println(m==n); } public static void println(Object o){ System.out.println(o); } }
作者:劉曉;花名:愚谷。
點擊 閱讀更多 查看更多詳情
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/73148.html
摘要:不過其中的流程算是一個簡易的實現,可以對加深一些理解。實現二因此如何來實現一個完整的緩存呢,這次不考慮過期時間的問題。緩存數量超過閾值時移除鏈表尾部數據。 showImg(https://segmentfault.com/img/remote/1460000014229173?w=1408&h=872); 前言 LRU 是 Least Recently Used 的簡寫,字面意思則是最...
摘要:對于數據結構哈希表我們在上一篇也已經詳細說了。鍵空間示意圖的數據庫就是使用字典哈希表來作為底層實現的,對數據庫的增刪改查都是構建在字典哈希表的操作之上的。 前言 只有光頭才能變強 今天繼續來學習Redis,上一篇從零單排學Redis【青銅】已經將Redis常用的數據結構過了一遍了。如果還沒看的同學可以先去看一遍再回來~ 這篇主要講的內容有: Redis服務器的數據庫 Redis對過期...
摘要:添加用戶接口類簡單用戶鏈接數據庫微服務通過注解標注該類為持久化操作對象。查找用戶數據保存用戶數據更新用戶數據刪除用戶數據這是清除緩存添加緩存配置緩存配置。對象是否永久有效,一但設置了,將不起作用。設置對象在失效前允許存活時間單位秒。 SpringCloud(第 045 篇)鏈接Mysql數據庫簡單的集成Mybatis、ehcache框架采用MapperXml訪問數據庫 - 一、大致介紹...
閱讀 2755·2019-08-30 15:53
閱讀 521·2019-08-29 17:22
閱讀 1040·2019-08-29 13:10
閱讀 2307·2019-08-26 13:45
閱讀 2751·2019-08-26 10:46
閱讀 3202·2019-08-26 10:45
閱讀 2504·2019-08-26 10:14
閱讀 467·2019-08-23 18:23