1.什么是自动装箱与自动拆箱
public class Main {
public static void main(String[] args) {
//自动装箱
Integer I = 10;
//自动拆箱
int i = total;
}
}
简单一点说,自动装箱就是可以将基本数据类型直接赋值给其对应的包装类;自动拆箱就是基本类型包装类中的值可以直接赋值给其对应的基本类型。
2.相关问题
2.1 赋值是的值类型问题。
先来看一个例子。
public class Demo_2 {
public static void main(String args[]) {
//Double d = 100; 会报错
Double dd = 100.0; //不会报错
}
}
两个赋值语句一个正确,一个错误。为什么会出现这样的问题,我们反编译一下看看。
public class autobox.Demo_2 {
public autobox.Demo_2();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: ldc2_w #2 // double 100.0d
3: invokestatic #4 // Method java/lang/Double.valueOf:(D)Ljava/lang/Double;
6: astore_1
7: return
}
可以看到在自动装箱的时候,调用了valueOf方法。这时我们看一下valueOf方法的源码。
public static Double valueOf(String s) throws NumberFormatException {
return new Double(parseDouble(s));
}
public static Double valueOf(double d) {
return new Double(d);
}
这里可以看到,valueOf方法可以接收两个参数double和String。所以报错的原因就清楚了,其他的几个基本类型包装类也是如此。
2.2 新建的两个包装类是否相等问题
先来看一个例子
public class Demo {
public static void main(String args[]) {
int i_1=59;
Integer i_2=59;
Integer i_3=59;
Integer i_4=new Integer(59);
System.out.println(i_1==i_2);//ture
System.out.println(i_1==i_3);//ture
System.out.println(i_2==i_3);//ture
System.out.println(i_3==i_4);//false
System.out.println(i_2==i_4);//false
}
}
前两个正确很好解释,因为基本类型与包装类进行比较的时候,包装类会进行自动拆箱,然后比较的就是int类型的值,所以两者相等。最后两个false也很好理解,都是新建的对象,那内存地址应该就是不同的,所以false。那为什么i_2==i_3是ture呢,同样是新建的对象,要解决这个问题,还是需要看看自动装箱所使用的valueOf方法。
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
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) {
try {
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);
} catch( NumberFormatException nfe) {
// If the property cannot be parsed into an int, ignore it.
}
}
high = h;
cache = new Integer[(high - low) + 1];
int j = low;
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++);
// range [-128, 127] must be interned (JLS7 5.1.7)
assert IntegerCache.high >= 127;
}
原来是有一个Integer类型的cache数组。这个数组已经提前创建并存储好了-128—127这之间的Integer类型,当自动装箱时赋的值是这些其中之一的话,就直接返回cache数组中对应的值。所以i_2==i_3是正确的。
需要注意的是这种cache数组只有整型的包装类才有,Double,Float这样的浮点型是没有的。