1. 简介
大家对基本数据类型都非常熟悉,例如 int、float、double、boolean、char 等。基本数据类型是不具备对象的特性,比如基本类型不能调用方法、功能简单。。。,为了让基本数据类型也具备对象的特性, Java 为每个基本数据类型都提供了一个包装类,这样我们就可以像操作对象那样来操作基本数据类型。
对象包装类是不变的,即一旦构造了包装类,就不允许更改包装在其中的值。同时,对象包装类还是final,因此不能定义它们的子类。
假设想定义一个整型数组列表,而尖括号中的类型参数不允许是基本类型的,也就是说,不允许写成ArrayList<int>。这里用到了对象包装类。我们可以声明一个Integer对象的数组列表。
ArrayList<Integer> list = new ArrayList<Integer>();
备注:
ArrayList<Integer>的效率远远低于int[] 数组,但是还是使用ArrayList,其原因就是程序员操作的方便性比执行效率更加重要。
进行如下操作:
list.add(3);
将自动转换为:
list.add(Integer.valueOf(3));
这种变换就是自动装箱。
相反的,当将一个Integer对象赋予一个int值时,将会自动拆箱:
int n = list.get(i)
将自动转换为:
int n = list.get(i).intValue();
备注:
装箱与拆箱是编译器认可的,而不是虚拟机。编译器在生成类的字节码时,插入必要的方法调用。虚拟机只是执行这些字节码。
使用数值对象包装类有一个好处:
可以将某些基本方法放置在包装类中。
int x = Integer.parseInt(s);
2. 分类
装箱:把基本类型转换成包装类,使其具有对象的性质,又可分为手动装箱和自动装箱
package com.qunar.test;
public class HelloWorld {
public static void main(String[] args) {
// 定义一个int基本类型值
int num = 14;
// 手动装箱
Integer x = new Integer(num);
// 自动装箱
Integer y = num;
System.out.println("x->"+x+" y->"+y);
}
}
拆箱:和装箱相反,把包装类对象转换成基本类型的值,又可分为手动拆箱和自动拆箱
package com.qunar.test;
public class HelloWorld {
public static void main(String[] args) {
// 定义一个Integer包装类
Integer integer = new Integer(8);
// 手动拆箱
int x = integer.intValue();
// 自动拆箱
int y = integer;
System.out.println("x->"+x+" y->"+y);
}
}
3. 分析
自动装箱的弊端:
自动装箱有一个问题,那就是在一个循环中进行自动装箱操作的情况,如下面的例子就会创建多余的对象,影响程序的性能:
Integer sum = 0;
for(int i=1000; i<5000; i++){
sum+=i;
}
上面的代码sum+=i可以看成sum = sum + i,但是+这个操作符不适用于Integer对象,首先sum进行自动拆箱操作,进行数值相加操作,最后发生自动装箱操作转换成Integer对象。其内部变化如下:
sum = sum.intValue() + i;
Integer sum = new Integer(result);
因此在我们编程时,需要注意到这一点,正确地声明变量类型,避免因为自动装箱引起的性能问题。