轉載請註明原文地址:http://www.javashuo.com/article/p-qkunbogr-ee.htmlhtml
咱們知道,Java有8大基本數據類型,4整2浮1符1布。java
咱們在實際開發中,除了使用到數據的值以外,還會涉及到對數據的操做。根據「面向對象」編程的思想,這些常見的操做被抽象成方法,封裝到了一個類中,一個基本數據類型對應一個這樣的類,這些類統稱爲「包裝類」。編程
8大基本類型 分別對應 8個包裝類,再加上兩個用於高精度運算的包裝類,共有10大包裝類。分別爲:數組
Byte:對應 byte 類型緩存
Short:對應 short類型jvm
Integer:對應 int類型ide
Long:對應 long類型函數
Float:對應 float類型工具
Double:對應 double類型性能
Character:對應 char類型
Boolean:對應 boolean類型
BigInteger:支持任意精度[長度]的整數運算。
BigDecmail:支持任意精度的浮點數運算,主要用於金額計算。
包裝類的好處:它提供了一系列操做本類型數據的方法,能夠爲咱們在開發過程當中操做8大基本類型數據提供充足的「工具」。
一、裝箱
把基本數據類型轉換成包裝類的過程就是打包裝,英文名boxing,翻譯爲裝箱。
二、拆箱
反之,把包裝類轉換成基本數據類型的過程就是拆包裝,英文對應於unboxing,中文翻譯爲拆箱。
三、自動拆裝箱
自動裝箱: 就是將基本數據類型自動轉換成對應的包裝類。
自動拆箱:就是將包裝類自動轉換成對應的基本數據類型。
四、自動拆裝箱的發生場景
1)自動拆裝箱的過程主要發生在賦值操做上:將一個基本數據類型的值符給包裝類變量,則進行自動裝箱操做;將一個包裝類變量的值賦給基本數據類型變量,則發生自動拆箱操做。
2)將基本數據類型放入集合類時:Java中的集合類只能接收對象類型,當咱們把基本數據類型放入集合類中的時候,會進行自動裝箱成對應的包裝類對象後再放入。
3)基本數據變量與包裝類變量進行運算操做時:基本數據變量與包裝類變量進行比較運算、數學運算、三目運算時,會自動拆箱成基本類型再進行運算。
4)函數返回值自動拆裝箱:當函數定義時,指定了函數返回值是包裝類,則return 一個基本數據類型值時,就會自動裝箱;若是定義的函數返回值是基本數據類型時,return一個包裝類對象會自動拆箱。
一、包裝對象的數值比較,不能簡單的使用==
,雖然-128到127之間的數字能夠[下文中解釋],可是這個範圍以外仍是須要使用equals
比較。【== 比較的是地址,equals比較的是值】
二、因爲自動拆箱,若是包裝類對象爲null,那麼自動拆箱時就有可能拋出NPE[null pointer exception]。
三、若是在一個for循環中有大量拆裝箱操做,會浪費不少資源。
詳情可參閱:Java中整型的緩存機制 這篇文章。
首先看個例子:
package com.javapapers.java;public class JavaIntegerCache { public static void main(String... strings) { Integer integer1 = 3; //整數3自動裝箱 Integer integer2 = 3; //整數3自動裝箱 if (integer1 == integer2) //兩個自動裝箱後對象比較 System.out.println("integer1 == integer2"); else System.out.println("integer1 != integer2"); Integer integer3 = 300;//整數300自動裝箱 Integer integer4 = 300;//整數300自動裝箱 if (integer3 == integer4)//兩個自動裝箱後對象比較 System.out.println("integer3 == integer4"); else System.out.println("integer3 != integer4"); }}
上面的代碼輸出的結果是:
integer1 == integer2
integer3 != integer4
也就是說:整數3自動裝箱後賦值給a、b兩個引用變量,這兩個引用指向的是同一個對象。
可是整數300自動裝箱後賦值給c、d兩個引用變量,這兩個引用指向的是不一樣對象。
那麼問題來了——都是自動裝箱,爲何不一樣數值自動裝箱的結果不同呢?——這是因爲Integer的緩存機制致使的。
在實際開發過程當中,會常常在不經意間就觸發了自動拆裝箱機制。咱們知道,自動裝箱會建立一個包裝類對象,一套程序跑下來,會生成多少個這樣的對象?那開銷得多大啊。
所以,出於節省內存和提升性能的目的,從Java5開始,爲咱們提供了Integer的緩存機制。
這個緩存機制是怎麼工做的呢?咱們來看一下Integer類的取值方法——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) //先判斷整數值爲是否處於IntegerCache.low~IntegerCache.high之間的緩存值 return IntegerCache.cache[i + (-IntegerCache.low)]; //是的話,則從緩存數組中取對應的包裝類對象之間返回 return new Integer(i);//否,則建立一個新的包裝類對象返回 }
從代碼中能夠看出,自動裝箱時,建立對象以前先從IntegerCache.cache中尋找,若是沒找到才使用new新建對象。
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=} 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; //默承認緩存的最小值是 -128 static final int high; //可緩存的最大值 static final Integer cache[]; //緩存數組 static { // high value may be configured by property 可緩存最大值可經過jvm參數指定 int h = 127; //默承認緩存最大值爲127 String integerCacheHighPropValue = sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high"); //從JVM參數中獲取可緩存最大值配置 if (integerCacheHighPropValue != null) { try { int i = parseInt(integerCacheHighPropValue); i = Math.max(i, 127);//將配置值與127之間取較大值,即:可緩存值最小爲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;//斷言:可緩存最大值必須大於等於127 } private IntegerCache() {} }
從上面能夠得知,Integer緩存數組中保存了 -128~h(h>=127) 的值的包裝類對象,其中h值能夠經過JVM參數 -XX:AutoBoxCacheMax=size
修改【這也是JVM調優的一個經常使用配置項】。
至於最小範圍 -128~127 之間,是由於這個範圍的數字是最被普遍使用的。
IntegerCache是Integer類中定義的一個private static
的內部類,所以在程序中,第一次使用Integer對象的時候會須要必定的額外時間來初始化這個緩存。
ByteCache用於緩存Byte對象:固定範圍: -128 到 127,不能更改。
ShortCache用於緩存Short對象:固定範圍: -128 到 127,不能更改。
LongCache用於緩存Long對象:固定範圍: -128 到 127,不能更改。
CharacterCache用於緩存Character對象:固定範圍: 0 到 127,不能更改。
舉個例子:
若是一個變量p的值是: -128至127之間的整數 true 和 false的布爾值 ‘\u0000’至 ‘\u007f’之間的字符 之間時,將p自動裝箱成a和b兩個對象,能夠直接使用a==b判斷a和b的值是否相等。