【转载】详解Java的自动装箱与拆箱(Autoboxing and unboxing)
什么是拆箱装箱
拆箱就是自动将包装器类型转换为基本数据类型。(Integer——> int)
装箱就是自动将基本数据类型转换为包装器类型。(int ——> Integer)
这个过程是自动执行的。
public class Main {
public static void main(String[] args) {
//自动装箱,系统自动执行:Integer emp= Integer.valueOf(9);
Integer emp= 9;
//自定拆箱,系统自动执行 :int empprim = emp.intValue();
int totalprim = emp;
}
}
装箱
-
Integer emp= Integer.valueOf(9);
valueOf(int i)源码:如果i小于-128或者大于等于128(不在-128~128之间),就创建一个Integer对象,否则执行SMALL_VALUES[i + 128]。public static Integer valueOf(int i) { return i >= 128 || i < -128 ? new Integer(i) : SMALL_VALUES[i + 128]; }
Integer类的构造函数:
private final int value; public Integer(int value) { this.value = value; } public Integer(String string) throws NumberFormatException { this(parseInt(string)); }
SMALL_VALUES:静态的Integer数组对象。已经被创建好了的,也就是说在i >= 128 || i < -128会创建不同的对象,在i < 128 && i >= -128会根据i的值返回已经创建好的指定的对象。
private static final Integer[] SMALL_VALUES = new Integer[256];
-
例如:
Integer i1 = 100; Integer i2 = 100; Integer i3 = 200; Integer i4 = 200; System.out.println(i1==i2); //true System.out.println(i3==i4); //false
100<128,会返回SMALL_VALUES里面创建好的同一个对象。所以i1和i2是同一个对象。
200>128,自动装箱执行new Integer(200),也就是说它们会分别创建两个不同的对象。因为对于Integer,在(-128,128]之间只有固定的256个值,所以为了避免多次创建对象,我们事先就创建好一个大小为256的Integer数组SMALL_VALUES,所以如果值在这个范围内,就可以直接返回我们事先创建好的对象就可以了。
但是Double类型会有无限个,所以不能提前创建,valueOf()直接创建新的对象。
Boolean类型:并没有创建对象,因为在内部已经提前创建好两个对象,因为它只有两种情况,这样也是为了避免重复创建太多的对象。
public static Boolean valueOf(boolean b) {
return b ? Boolean.TRUE : Boolean.FALSE;
} -
另一种情况:包装类与基本数据类型比较。
= =
:说明num1 == num2时自动拆箱。
什么时候拆箱:
当一个基础数据类型与封装类进行==、+、-、*、/运算时,会将封装类进行拆箱,对基础数据类型进行运算。
当 “==”运算符的两个操作数都是包装器类型的引用,则是比较指向的是否是同一个对象,而如果其中有一个操作数是表达式(即包含算术运算)则比较的是数值(即会触发自动拆箱的过程)。Integer num1 = 400; int num2 = 400; System.out.println(num1 == num2); //true
equals
:源码里先将基本数据类型装箱,然后比较值。Integer num1 = 100; int num2 = 100; System.out.println(num1.equals(num2)); //true
源码:需要满足装箱后的类型相同以及内容相同。
public boolean equals(Object o) { return (o instanceof Integer) && (((Integer) o).value == value); }
拆箱:
-
intValue():
public int intValue() { return value; }
-
举例:
Integer integer100 = null; int int100 = integer100;
这两行代码是完全合法的,完全能够通过编译的,但是在运行时,就会抛出空指针异常。其中,integer100为Integer类型的对象,它当然可以指向null。但在第二行时,就会对integer100进行拆箱,也就是对一个null对象执行intValue()方法,当然会抛出空指针异常。所以,有拆箱操作时一定要特别注意封装类对象是否为null。