為什麼會需要包裝類型
我們知道Java是一個面相對象的程式設計語言,基本類型并不具有對象的性質,為了讓基本類型也具有對象的特征,就出現了包裝類型(如我們在使用集合類型Collection時就一定要使用包裝類型而非基本類型),它相當于将基本類型“包裝起來”,使得它具有了對象的性質,并且為其添加了屬性和方法,豐富了基本類型的操作。
當需要往ArrayList,HashMap中放東西時,像int,double這種基本類型是放不進去的,因為容器都是裝object的,這是就需要這些基本類型的包裝器類了。
Java的基本類型(中繼資料)與對應的包裝類型:
基本類型 | 基本類型大小 | 包裝類型 |
---|---|---|
byte | 1個位元組 | Byte |
shot | 2個位元組 | Short |
int | 4個位元組 | Integer |
long | 8個位元組 | Long |
float | 4個位元組 | Float |
double | 8個位元組 | Double |
char | 取決于底層儲存的字元 | Character |
boolean | Boolean |
包裝類的缺點:
在 64 位的 Java 虛拟機中,每一個 Java 對象在記憶體中的額外開銷就最少是16 個位元組。以 Integer 類為例,它僅有一個 int 類型的私有字段,占 4 個位元組。是以,每一個 Integer 對象的額外記憶體開銷至少是int的400%
什麼是自動裝箱和拆箱
自動裝箱:将基本的類型資料轉換為對應的包裝包裝類型資料
Integer a = 1;//裝箱
自動拆箱:将包裝類型轉換為基本類型資料
int b = a; //拆箱
自動拆箱和裝箱的實作
下面是很簡單的自動裝箱與自動拆箱的代碼,進過反編譯結果在下圖:
當進行自動裝箱時代用的是valueOf()方法
當進行自動拆箱時,代用的是intValue()方法
IntegerCahe分析
IntegerCache的詳細可以看:https://blog.csdn.net/zx6571269/article/details/82026879 這篇文章是轉載的個人感覺寫的非常好
Integer裡面隻有一個value屬性.
swap主要用于交換兩個Integer對象在棧裡面的資料。
private static void swap(Integer a,Integer b) throws NoSuchFieldException, IllegalAccessException {
Field valueField = Integer.class.getDeclaredField("value");
valueField.setAccessible(true);
int temp = valueField.getInt(a);
valueField.setInt(a,b.intValue());
valueField.setInt(b,temp);
}
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
Integer a=,b=;
swap(a,b);
System.out.println("a=:"+a);
System.out.println("b=:"+b);
Integer c=;
System.out.println("c=:"+c);
System.out.println("b=:"+b);
}
大家可以猜猜結果:
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 = -;
static final int high;
static final Integer cache[];
static {
// high value may be configured by property
int h = ;
//查找JVM,Integer初始化的緩存設定
String integerCacheHighPropValue =
sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
if (integerCacheHighPropValue != null) {
try {
int i = parseInt(integerCacheHighPropValue);
i = Math.max(i, );
// Maximum array size is Integer.MAX_VALUE
h = Math.min(i, Integer.MAX_VALUE - (-low) -);
} catch( NumberFormatException nfe) {
// If the property cannot be parsed into an int, ignore it.
}
}
high = h;
//建立緩存數組
cache = new Integer[(high - low) + ];
int j = low;
for(int k = ; k < cache.length; k++)
cache[k] = new Integer(j++);
// range [-128, 127] must be interned (JLS7 5.1.7)
assert IntegerCache.high >= ;
}
private IntegerCache() {}
}
IntegerCache是一個靜态的内部類,當,第一次初始化化是,,
int c = 1
反編譯後的
Integer c = Integer.valueOf((int)1);
其中java.lang.Integer.IntegerCache.high的取值範圍,它預設的範圍是[-128,127]之間。在該區間内所有的
Integer.valueOf(int)
函數傳回的對象,是根據int值計算的偏移量,從數組
Integer.IntegerCache.cache
中擷取,對象是同一個,不會建立對象。是以當我們修改了Integer.valueOf(1)的value後,所有
Integer.IntegerCache.cache[ 1 - IntegerCache.low ]
的傳回值都會變更。
包裝類 | 是否有Cache | 範圍 |
---|---|---|
Byte | ByteCache | [-128,127](固定) |
Short | ShortCache | [-128,127](固定) |
int | IntegerCache | [-128,Integer.MAX_VALUE - (-low) -1] |
long | LongCache | [-128,127](固定) |
float | – | – |
Double | – | – |
Character | CharacterCache | [0,127] |
Boolean | – | – |
參考1:https://www.jb51.net/article/129640.htm
參考2:https://www.cnblogs.com/dolphin0520/p/3780005.html
參考3:https://docs.oracle.com/javase/tutorial/java/data/autoboxing.html