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个,分别是: