Java中基礎數據類型與它們對應的包裝類見下表(共8種):java
原始類型 | 包裝類型 |
---|---|
boolean | Boolean |
byte | Byte |
char | Character |
float | Float |
int | Integer |
long | Long |
short | Short |
double | Double |
當表格中左邊列出的基礎類型與它們的包裝類有以下幾種狀況時,編譯器會自動幫咱們進行裝箱或拆箱.程序員
咱們看一段日常很常見的代碼面試
public void testAutoBox() {
List<Float> list = new ArrayList<>();
list.add(1.0f);
float firstElement = list.get(0);
}
複製代碼
list集合存儲的是Float包裝類型,我傳入的是float基礎類型,因此須要進行裝箱,而最後的get方法返回的是Float包裝類型,咱們賦值給float基礎類型,因此須要進行拆箱,很簡單,安排的明明白白bash
既然編譯器幫咱們自動進行了裝箱,拆箱,那麼編譯器到底作了些什麼,要搞清楚這些,最簡單直接的方式就是看類通過編譯器編譯後的字節碼,下面是上面一段代碼的字節碼實現ui
public testAutoBox()V
L0
LINENUMBER 15 L0
NEW java/util/ArrayList
DUP
INVOKESPECIAL java/util/ArrayList.<init> ()V
ASTORE 1
L1
LINENUMBER 16 L1
ALOAD 1
FCONST_1
INVOKESTATIC java/lang/Float.valueOf (F)Ljava/lang/Float;
INVOKEINTERFACE java/util/List.add (Ljava/lang/Object;)Z
POP
L2
LINENUMBER 17 L2
ALOAD 1
ICONST_0
INVOKEINTERFACE java/util/List.get (I)Ljava/lang/Object;
CHECKCAST java/lang/Float
INVOKEVIRTUAL java/lang/Float.floatValue ()F
FSTORE 2
L3
LINENUMBER 18 L3
RETURN
複製代碼
###因此結果很明顯了,以float和Float爲例,裝箱就是調用Float的valueOf方法new一個Float並賦值,拆箱就是調用Float對象的floatValue方法並賦值返回給float。其餘基礎類型都是大同小異的,具體能夠查看源碼。spa
##自動裝箱、拆箱中的坑 ###面試題中常常會有考點就是考察面試者對Java中自動裝箱、拆箱是否瞭解透徹,好比下面這一道面試題?指針
public void testAutoBox2() {
//1
int a = 100;
Integer b = 100;
System.out.println(a == b);
//2
Integer c = 100;
Integer d = 100;
System.out.println(c == d);
//3
c = 200;
d = 200;
System.out.println(c == d);
}
複製代碼
請問執行結果是多少?
code
題目很常見啦,客官別見笑,咱們來分析一下,orm
結果是否是很詭異,咱們直接去看Integer類valueOf方法的實現(JDK8的實現)cdn
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
複製代碼
能夠看到,這裏的實現並非簡單的new Integer,而是用IntegerCache作一個cache,cache的range是能夠配置的
private static class IntegerCache {
static final int low = -128;
static final int high;
static final Integer cache[];
static {
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++);
....
複製代碼
這是IntegerCache靜態代碼塊中的一段,默認Integer cache 的下限是-128,上限默認127,能夠配置,因此到這裏就清楚了,咱們上面當賦值100給Integer時,恰好在這個range內,因此從cache中取對應的Integer並返回,因此二次返回的是同一個對象,因此==比較是相等的,當賦值200給Integer時,不在cache 的範圍內,因此會new Integer並返回,固然==比較的結果是不相等的。
###以上
附錄1:JVM字節碼整型的入棧指令有4個,分別是: