浅谈java中自动装箱和拆箱
概念
装箱:将基本数据类型包装成对应的包装器类型,
拆箱:讲包装器类型拆成对应的基本数据类型
适用场景:
装箱:包装器类型中的equal()方法中,传参如果是基本数据类型,就会装箱成包装器类型。
@Override
public boolean equals(Object o) {
return (o instanceof Long) && (((Long) o).value == value);
}
比如说Long类型的equal方法,如果传入的是long的基本数据类型,则会自动转换成Long类型,再去比较类 型的value。
equal方法中比较的结果有两个,一个是类型,第二个是值。
拆箱:基本数据类型中==、+、-、*、/进行运算时,都会将封装类拆箱成基本数据类型进行运算。
测试:
Integer I = 257;
Integer I2 = 257;
int i = 257;
long l = 257;
Long L = new Long(257);
System.out.println(l == L); // t
System.out.println(l == i); // t
System.out.println(i == I); // t
System.out.println(i == I2); // t
System.out.println(I == I2); // f
System.out.println(I.equals(i)); // t
System.out.println(I.equals(I2)); // t
System.out.println(I.equals(l)); // f
System.out.println(I.equals(L)); // f
源码分析:
装箱:
Integer中的初始化方法,它有个valueOf的方法,里面就是将一个int基本数据类型的值包装成一个Integer对象返回出来(Long类型一样),如果是值是在-128-127之间,Integer是不会去生成新的Integer对象的,而是会去数组(缓存)中去取这个对象,因此,两个-128-127之间的Integer对象使用valueOf返回出来的是同一个对象,用==进行判断会返回true
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
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中因为每个整型之间都有无穷的量,因此,它每次执行valueOf方法时都会返回一个新的Double对象,每次用==比较就会返回false
public static Double valueOf(String s) throws NumberFormatException {
return new Double(parseDouble(s));
}
最后有一点就是effective Java中第五条中避免创建不必要的对象中提到:
要优先使用基本类型而不是装箱基本类型,当心无意识的自动装箱
public static void main(String[] args) {
Long sum = 0L;
for(long i =0 ;i<Integer.MAX_VALUE;i++){
sum +=i;
}
System.out.println(sum);
}
当Long对象进行运算时,会自动拆成基本数据类型,在生成一个新的Long对象,因此这个方法会生成大量的Long对象,其实这是很没有必要的。
拆箱的源码返回它的value
public int intValue() { return value; }
需要包装类型的原因是因为基本数据类型不具备面对对象的特性,不能存放Max,Min等属性