您好,登錄后才能下訂單哦!
今天小編給大家分享一下Java自動裝箱、自動拆箱與Integer緩存怎么使用的相關知識點,內容詳細,邏輯清晰,相信大部分人都還太了解這方面的知識,所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來了解一下吧。
自動裝箱和自動拆箱是什么?Integer緩存是什么?它們之間有什么關系?
先來看一道題目。
Integer a = new Integer(1); Integer b = new Integer(1); System.out.println(a==b); Integer c = 1; Integer d = 1; System.out.println(c==d); Integer e = 128; Integer f = 128; System.out.println(e==f);
先答,后看答案。
答案是false true false,你答對了嗎?
既然一塊出現了,就一起串一下知識點
Java中基本數據類型有八種,可以分為三類:
字符型:char
布爾型:boolean
數值型:byte short int long float double
包裝類是將八種基本數據類型包裝為了類,使它們可以使用Java的三大特性:封裝、繼承、多態。對應關系如下:
基本數據類型 | 對應的包裝類 |
---|---|
byte | Byte |
short | Short |
int | Integer |
long | Long |
float | Float |
double | Double |
boolean | Boolean |
char | Character |
數值型對應的六個包裝類都繼承于Number類。
八種基本數據類型對應八種包裝類,那么它們是怎么進行數據轉換的?
//基本數據類型轉包裝類 //1.有參構造 Integer a = new Integer(1); //2.實際上,有參構造的參數也可以是字符串,不過要使用正確的數據,“123abc”不可能會轉換為Integer類型 Integer b = new Integer("123"); //3.valueOf() Integer c = Integer.valueOf(123); //包裝類轉基本數據類型(xxxValue() float是floatValue() double是doubleValue()) int d = a.intValue();
以上的形式都是比較符合認知的,獲取一個對象可以通過new或者調用某個方法,獲取一個值就調用對象的某個屬性。
Java 5.0之后可以不用這么麻煩了,增加了自動裝箱和自動拆箱的新特性,實際上兩個概念非常好理解。
int a = 10; Integer b = a; //自動裝箱 int c = b; //自動拆箱
乍一看,對象=數值的這種形式并不符合認知,但是借助于自動裝箱和自動拆箱就可以實現。實際上,編譯器還是借助于valueOf()和xxxValue()實現的。
我們來看一下valueOf()源碼。
/** * Returns an {@code Integer} instance representing the specified * {@code int} value. If a new {@code Integer} instance is not * required, this method should generally be used in preference to * the constructor {@link #Integer(int)}, as this method is likely * to yield significantly better space and time performance by * caching frequently requested values. * * This method will always cache values in the range -128 to 127, * inclusive, and may cache other values outside of this range. * * @param i an {@code int} value. * @return an {@code Integer} instance representing {@code i}. * @since 1.5 */ public static Integer valueOf(int i) { if (i >= IntegerCache.low && i <= IntegerCache.high) return IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer(i); }
valueOf()并不是簡單地返回Integer對象,而是先進行了一次判斷,輸入的數據符合某個范圍的話,將會返回一個特定的對象,從注釋上來看,這個范圍默認是[-128,127],并且可能是更大的范圍;而超過這個范圍就會返回new的對象。而使用到的IntegerCache數據就是Integer的緩存了。
數值計算日常使用比較頻繁,那如果不停的去new Integer對象的話,開銷會非常大,所以,Java在執行程序時會自動生成一個靜態數組作為緩存,Integer默認對應的緩存數組范圍在[-128,127],只要數據在這個范圍內,就可以從緩存中拿到相應的對象。
看一下IntegerCache源碼。
/** * 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 property int 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_VALUE h = 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是Integer的靜態內部類,valueOf()調用的IntegerCache.cache就是一個數組對象,數組的大小取決于范圍內的最大值和最小值,默認是[-128,127],當然,(注釋上說)也可以通過JVM修改這個范圍(這我不了解)。然后數組內的元素都會被賦一個Integer對象,緩存也就形成了。
存在數組緩存,也就意味著,如果取值在[-128,127],使用valueOf()或者自動裝箱創建的Integer對象都是在數組中取出,因此對象指向的內存地址是完全一樣的。而如果用new或者是超出這個范圍都要重新創建對象。
當然,不止Integer有緩存機制,Byte、Short、Long、Character都具有緩存機制。其中Byte,Short,Integer,Long的范圍為 -128 到 127,Character的范圍為 0 到 127。
Integer a = new Integer(1); Integer b = new Integer(1); System.out.println(a==b); Integer c = 1; Integer d = 1; System.out.println(c==d); Integer e = 128; Integer f = 128; System.out.println(e==f);
1.new創建的兩個對象,即使值相同,指向的內存地址也是不同的,使用==進行比較返回結果為false
2.自動裝箱和緩存機制,兩個對象實際上是相同的,返回結果為true
3.超出緩存范圍,執行時會new新對象,兩個對象不同,返回結果為false
以上就是“Java自動裝箱、自動拆箱與Integer緩存怎么使用”這篇文章的所有內容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會為大家更新不同的知識,如果還想學習更多的知識,請關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。