装箱和拆箱
也叫装包拆包,装包是把那八种基本数据类型转换为它的包装类,拆包则相反
上面这俩种方式都是装包,下面是它的字节码文件
用到了Integer的ValueOf方法:
就是返回了一个Integer类的对象,把它的value属性设置成了指定的值。
下面是拆包:
用到了intValue方法:
自动装箱拆箱,显式装箱拆箱
这是自动装箱拆箱
这是显式装箱和拆箱
看一下八种数据类型自动装箱的源码:
//boolean原生类型自动装箱成Boolean
public static Boolean valueOf(boolean b) {
return (b ? TRUE : FALSE);
}
//byte原生类型自动装箱成Byte
public static Byte valueOf(byte b) {
final int offset = 128;
return ByteCache.cache[(int)b + offset];
}
//short原生类型自动装箱成Short
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);
}
//char原生类型自动装箱成Character
public static Character valueOf(char c) {
if (c <= 127) { // must cache
return CharacterCache.cache[(int)c];
}
return new Character(c);
}
//int原生类型自动装箱成Integer
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
//long原生类型自动装箱成Long
public static Long valueOf(long l) {
final int offset = 128;
if (l >= -128 && l <= 127) { // will cache
return LongCache.cache[(int)l + offset];
}
return new Long(l);
}
//double原生类型自动装箱成Double
public static Double valueOf(double d) {
return new Double(d);
}
//float原生类型自动装箱成Float
public static Float valueOf(float f) {
return new Float(f);
}
可以发现除了Double和Float类型只是new一个新对象,其他类型都用到了cache方法,也就是用到了缓存策略
为什么使用缓存策略:缓存中的对象都是经常使用的,可以避免每次装箱都new一个新的对象,导致浪费内存
而double和float没有经常使用的,所以就没必要用到缓存策略
有趣的面试题
结果是:true false
这是因为缓存中的Integer数据的范围是从-128到127,100在此范围内,所以不用产生新对象,200不再此范围内,所以每次装箱都要new一个新对象
包装类的比较
这是因为:
当==左右两边是包装类的引用时,比较的是指向的对象
当==左右俩边有算数运算符时,比较的是对象的value属性,即数值
包装类的equals方法比较的也是数值,如下: