装箱 就是把“值类型”转换成“引用类型”; 拆箱 就是把“引用类型”转换成“值类型”;
把“值类型”转换成“引用类型”
int i = 10; //值类型 object o = i; //引用类型具体过程:
在堆中申请内存,内存大小为值类型的大小,再加上额外固定空间(类型对象指针和同步块索引)。将值类型的字段值拷贝到新分配的内存中。返回新引用对象的内存地址(给栈上的引用)。我们可以从图中看到,装箱就是生成图中除了一开始 i=1 的变量之外另外两块变量的过程。
把“引用类型”转换成“值类型”
int j = (int)o;拆箱不是直接将装箱过程倒过来,拆箱的代价比装箱要低的多,拆箱其实就是获取一个指针的过程。一个已装箱的实例在拆箱时,编译器在内部都干了下面这些事:
如果包含了“对已装箱类型的实例引用”的变量为null时,会抛出一个NullReferenceException异常。如果引用指向的对象不是所期待的值类型的一个已装箱实例,会抛出一个InvalidCastException异常与拆箱比较,装箱的性能消耗更大,因为引用对象的分配更加复杂,成本也更高,值类型分配在栈上,分配和释放的效率都很高。装箱过程需要创建一个新的引用类型对象实例。使用泛型可以减少装箱拆箱操作
ArrayList list = new ArrayList(); //Add方法使用的object类型参数 //List<int> list = new List<int>(); //Add方法使用的int类型参数 list.Add(1);