1、简介
装箱:自动把基本类型转化为包装器类型
拆箱:自动把包装器类型转化为基本类型
2、主要对应的包装器类型
byte (1字节) Byte
short (2字节) Short
int (4字节) Integer
long (8字节) Long
float (4字节) Float
double (8字节) Double
char (2字节) Char
boolean () Boolean
3、实现
以Integer为例:装箱的时候自动调用的是Integer的valueOf(int)方法。拆箱的时候自动调用的是Integer的intValue方法,其他类似。
Integer、Short、Byte、Character、Long这几个类的valueOf方法的实现是类似的。例如Short,如果在-128到127之间,会走ShortCache,超过这个范围会new对象。所以做比较时,在-128到127之间可以用“==”,超过这个范围需要用equals,否则返回false。
public static Short valueOf(short s) { final int offset = 128; int sAsInt = s; if (sAsInt >= -128 && sAsInt <= 127) { // must cache return ShortCache.cache[sAsInt + offset]; } return new Short(s); }
Double、Float的valueOf方法的实现是类似的,例如Double,调用的valueOf(String s):
public static Double valueOf(String s) throws NumberFormatException { return new Double(FloatingDecimal.readJavaFormatString(s).doubleValue()); } public static Double valueOf(double d) { return new Double(d); }
4、缓存数据
Integer、Short、Byte、Character、Long这几个类中都有个内部缓存类,Double、Float的类中没有。
Byte,Short,Long 有固定范围: -128 到 127。对于 Character, 范围是 0 到 127。除了 Integer 可以通过参数改变范围外,其它的都不行
以Integer为例,缓存类IntegerCache,缓存了-127到128的数据,不管创建多少个这个范围内的Integer用ValueOf出来的都是同一个对象,减少了new的时间也就提升了效率。同时JDK还提供cache中high值得可配置。
Short、Byte、Character、Long类中也实现了类似的缓存类,但是没有提供high值的配置。
private static class IntegerCache { static final int low = -128; static final int high; static final Integer cache[]; static { // high value may be configured by property int h = 127; String integerCacheHighPropValue = sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high"); if (integerCacheHighPropValue != null) { 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); } high = h; cache = new Integer[(high - low) + 1]; int j = low; for(int k = 0; k < cache.length; k++) cache[k] = new Integer(j++); } private IntegerCache() {} }
5、==和equals
==基本数据类型比较内容,实质也是比较地址(因为对于基本类型来说,当值相同的时候,地址也是相同的),对象比较比较地址。对于java中的“==”操作符号,jvm会根据两边互相比较的操作数的数据类型,来调用不同的指令。对于于boolean,byte、short、int、long这种整形操作数,会生成 if_icmpne指令,该指令用于比较整形数值是否相等。如果操作数是对象的话,编译器则会生成if_acmpne指令,与if_icmpne相比将i(int)改成了a(object reference)。
equals是Object类中的方法,所有继承Object的类都有此方法。Object类中,equals方法是用来比较两个对象的引用是否相等,即是否指向同一个对象。像String中的equals都是对这个方法的重写,比较的是所指向的对象的内容。
6、面试常问的一个问题:
Integer i = new Integer("123")和Integer i = 123;这两种方式的区别
答:第一种方式不会触发自动装箱的过程,直接new对象;而第二种方式会触发装箱过程;