自动拆装箱
前言
我们知道Java共有8种基本数据类型int、byte、short、long、float、double、char、boolean,对应的包装类分别为Integer、Byte、Short、Long、Float、Double、Character、Boolean。既然有了基本数据类型,那么为什么还需要包装类呢。主要因为Java是一种面向对象的语言,很多地方需要使用对象而不是基本数据类型。比如在集合类中,我们无法将int、double等类型放进去,因为集合的容器要求元素是Object类型。为了让基本数据类型也具有对象的特征,就出现了包装类型,相当于将基本数据类型"包装起来",使得基本数据类型具有对象的性质,并且为其添加了属性和方法,丰富了基本数据类型的操作。
什么是自动拆装箱
- 装箱: 就是把基本数据类型转化成对应的包装类
- 拆箱: 就是把包装类型转化成对应的基本数据类型
- 自动装箱: 就是将基本数据类型自动转换成对应的包装类
- 自动拆箱:就是将包装类自动转换成对应的基本数据类型
Java SE5之前如果要生成一个值为1的对象需要以下操作
Integer i = new Integer(1);
Java SE5之后,提供了自动拆装箱的功能,只需要以下操作
Integer i = 1;#自动装箱
int j =i;#自动拆箱
自动拆装箱的实现原理
举个例子
public class Demo {
public static void main(String[] args) {
Integer i = 1;
int j = i;
}
}
字节码如下
从以上的字节码来看,Java自动装箱调用了Integer.valueof()方法,自动拆箱调用了Integer.intValue()方法,其他包装类的自动拆装箱类似
什么时候会用到自动拆装箱
1.赋值
Integer i = 1;#自动装箱,调用 Integer.valueOf()
int j =i;#自动拆箱,调用 Integer.intValue()
2.逻辑、算术运算
Integer i = 1;
int j = 2;
int z = i + j;
Boolean flag = i > j ? true : false;
反编译后
Integer i = Integer.valueOf(1);
int j = 2;
int z = i.intValue() + j;
Boolean flag = Boolean.valueOf(i.intValue() > j);
3.将基本数据类型放到集合里面
ArrayList<Integer> list = new ArrayList<>();
list.add(1);
反编译后
ArrayList<Integer> list = new ArrayList();
list.add(Integer.valueOf(1));
4.函数调用
public static void main(String[] args) {
sum(2);
}
public static Integer sum(Integer i){
return 0;
}
反编译后
public static void main(String[] args)
{
sum(Integer.valueOf(2));
}
public static Integer sum(Integer i)
{
return Integer.valueOf(0);
}
自动拆装箱的问题
我们来看下面的代码
Integer i = 128;
Integer j = 128;
Integer x = 1;
Integer y = 1;
System.out.println(i==j);#false
System.out.println(x == y);#true
上面为什么会出现这样的结果,主要是由于Integer的缓存机制,我们来看一下Integer的源码
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
Integer默认的缓存范围是 -128~127,当在这一范围时,不会生成新的对象;当超过这一范围后,才生成新的Integer对象。当然缓存机制不只有Integer有,比如:
- Boolean,缓存了true/false对应实例,确切的说,返回两个常量实例Boolean.TRUE/FALSE
- Short,缓存了 ~128-127的数值
- Byte,数值有限,全部被缓存
- Character,缓存范围‘ \u0000 ' 到 ’ \u007F '