有八种基本数据类型,就有八种基本数据类型的包装类型,就以int的包装类型(Integer)为例,主要介绍下装箱与拆箱:
Integer i1=-127;
Integer i2=-127;
System.out.println(i1==i2);// 1 true
System.out.println(i1==-127);// 2 true
Integer i3=128;
Integer i4=128;
System.out.println(i3==i4);// 3 false
System.out.println(i3==128);// 4 true
对于注释1,Integer包装类型的自动装箱将常量大小为1个字节(即-128-127)的值维护在一个常量池中,所以i1和i2引用同一对象,==比较的是地址值,故1为true。对于注释2,由于包装类型在表达式中至少有一个不是包装类型,所以i1会自动拆箱为基本类型进行比较,所以数值比较为true。
对于注释3,由于128超过了Integer包装类型维护的常量大小(1个字节),所以i1和i2引用的是两个对象,故打印false。对于注释4和注释2同一原理,故打印true。
Integer i=1;i+=1;该语句的详细过程说明:
首先Integer i=1,做了自动装箱(使用valueOf()方法将int装箱为Integer类型),接着i+=1,先将Integer类型的i自动拆箱成int(使用intValue()方法将Integer拆箱为int),完成加法运行之后的i再装箱成Integer类型。
自动装箱拆箱机制:
java 1.5开始的自动装箱拆箱机制其实是编译时自动完成替换的,装箱阶段自动替换为了valueOf方法,拆箱阶段自动替换为了xxxValue方法。对于Integer类型的valueOf方法参数如果是-128~127之间的值会直接返回内部缓存池中已经存在对象的引用,参数是其他范围值则返回新建对象;而Double的区别在于不管传入的参数值是多少都会new一个对象来表达该数值(因为在指定范围内浮点型数据个数是不确定的,整型等个数是确定的,所以可以Cache)。
注意:Integer、Short、Byte、Character、Long的valueOf方法实现类似,而Double和Float比较特殊,每次返回新包装类对象,对于两边都是包装类型的比较==比较的是引用,equals比较的是值,对于两边有一边是表达式(包含算术运算)则==比较的是数值(自动融发拆箱过程),对于包装类型equals方法不会进行类型转换。