转自:  http://www.cnblogs.com/anding/p/5236739.html

常见面试题目:

1.什么是拆箱和装箱?

2.什么是箱子?

3.箱子放在哪里?

4.装箱和拆箱有什么性能影响?

5.如何避免隐身装箱?

6.箱子的基本结构?

7.装箱的过程?

8.拆箱的过程?

9.下面这段代码输出什么?共发生多少次装箱?多少次拆箱?

int i = 5;
object obj = i;
IFormattable ftt = i;
Console.WriteLine(System.Object.ReferenceEquals(i, obj));
Console.WriteLine(System.Object.ReferenceEquals(i, ftt));
Console.WriteLine(System.Object.ReferenceEquals(ftt, obj));
Console.WriteLine(System.Object.ReferenceEquals(i, (int)obj));
Console.WriteLine(System.Object.ReferenceEquals(i, (int)ftt));

深入浅出装箱与拆箱

有拆必有装,有装必有拆。

在上一文中我们提到,所有值类型都是继承自System.ValueType,而System.ValueType又是来自何方呢,不难发现System.ValueType继承自System.Object。因此Object是.NET中的万物之源,几乎所有类型都来自她,这是装箱与拆箱的基础。

特别注意的是,本文与上一文有直接关联,需要先了解上一文中值类型与引用类型的原理,才可以更好理解本文的内容。

 基本概念

拆箱与装箱就是值类型与引用类型的转换,她是值类型和引用类型之间的桥梁,他们可以相互转换的一个基本前提就是上面所说的:Object是.NET中的万物之源

先看看一个小小的实例代码:

            int x = 1023;object o = x; //装箱int y = (int) o; //拆箱

装箱:值类型转换为引用对象,一般是转换为System.Object类型或值类型实现的接口引用类型;

拆箱:引用类型转换为值类型,注意,这里的引用类型只能是被装箱的引用类型对象;

由于值类型和引用类型在内存分配的不同,从内存执行角度看,拆箱与装箱就势必存在内存的分配与数据的拷贝等操作,这也是装箱与拆箱性能影响的根源。

 装箱的过程

int x = 1023;
object o = x; //装箱

装箱就是把值类型转换为引用类型,具体过程:

  • 1.在堆中申请内存,内存大小为值类型的大小,再加上额外固定空间(引用类型的标配:TypeHandle和同步索引块);
  • 2.将值类型的字段值(x=1023)拷贝新分配的内存中;
  • 3.返回新引用对象的地址(给引用变量object o)

如上图所示,装箱后内存有两个对象:一个是值类型变量x,另一个就是新引用对象o。装箱对应的IL指令为box,上面装箱的IL代码如下图:

 拆箱的过程

int x = 1023;
object o = x; //装箱
int y = (int) o; //拆箱

明白了装箱,拆箱就是装箱相反的过程,简单的说是把装箱后的引用类型转换为值类型。具体过程:

  • 1.检查实例对象(object o)是否有效,如是否为null,其装箱的类型与拆箱的类型(int)是否一致,如检测不合法,抛出异常;
  • 2.指针返回,就是获取装箱对象(object o)中值类型字段值的地址;
  • 3.字段拷贝,把装箱对象(object o)中值类型字段值拷贝到栈上,意思就是创建一个新的值类型变量来存储拆箱后的值;

如上图所示,拆箱后,得到一个新的值类型变量y,拆箱对应的IL指令为unbox,拆箱的IL代码如下:

 装箱与拆箱总结及性能

装的的什么?拆的又是什么?什么是箱子?

通过上面深入了解了装箱与拆箱的原理,不难理解,只有值类型可以装箱,拆的就是装箱后的引用对象,箱子就是一个存放了值类型字段的引用对象实例,箱子存储在托管堆上。只有值类型才有装箱、拆箱两个状态,而引用类型一直都在箱子里。

关于性能

之所以关注装箱与拆箱,主要原因就是他们的性能问题,而且在日常编码中,经常有装箱与拆箱的操作,而且这些装箱与拆箱的操作往往是在不经意时发生。一般来说,装箱的性能开销更大,这不难理解,因为引用对象的分配更加复杂,成本也更高,值类型分配在栈上,分配和释放的效率都很高。装箱过程是需要创建一个新的引用类型对象实例,拆箱过程需要创建一个值类型字段,开销更低。

为了尽量避免这种性能损失,尽量使用泛型,在代码编写中也尽量避免隐式装箱。

什么是隐式装箱?如何避免?

就是不经意的代码导致多次重复的装箱操作,看看代码就好理解了

int x = 100;
ArrayList arr = new ArrayList(3);
arr.Add(x);
arr.Add(x);
arr.Add(x);

这段代码共有多少次装箱呢?看看Add方法的定义:

再看看IL代码,可以准确的得到装箱的次数:

显示装箱可以避免隐式装箱,下面修改后的代码就只有一次装箱了。

int x = 100;
ArrayList arr = new ArrayList(3);
object o = x;
arr.Add(o);
arr.Add(o);
arr.Add(o);

题目答案解析:

1.什么是拆箱和装箱?

装箱就是值类型转换为引用类型,拆箱就是引用类型(被装箱的对象)转换为值类型。

2.什么是箱子?

就是引用类型对象。

3.箱子放在哪里?

托管堆上。

4.装箱和拆箱有什么性能影响?

装箱和拆箱都涉及到内存的分配和对象的创建,有较大的性能影响。

5.如何避免隐身装箱?

编码中,多使用泛型、显示装箱。

6.箱子的基本结构?

上面说了,箱子就是一个引用类型对象,因此她的结构,主要包含两部分:

  • 值类型字段值;
  • 引用类型的标准配置,引用对象的额外空间:TypeHandle和同步索引块,关于这两个概念在本系列后面的文章会深入探讨。

7.装箱的过程?

  • 1.在堆中申请内存,内存大小为值类型的大小,再加上额外固定空间(引用类型的标配:TypeHandle和同步索引块);
  • 2.将值类型的字段值(x=1023)拷贝新分配的内存中;
  • 3.返回新引用对象的地址(给引用变量object o)

8.拆箱的过程?

  • 1.检查实例对象(object o)是否有效,如是否为null,其装箱的类型与拆箱的类型(int)是否一致,如检测不合法,抛出异常;
  • 2.指针返回,就是获取装箱对象(object o)中值类型字段值的地址;
  • 3.字段拷贝,把装箱对象(object o)中值类型字段值拷贝到栈上,意思就是创建一个新的值类型变量来存储拆箱后的值;

9.下面这段代码输出什么?共发生多少次装箱?多少次拆箱?

int i = 5;
object obj = i;
IFormattable ftt = i;
Console.WriteLine(System.Object.ReferenceEquals(i, obj));
Console.WriteLine(System.Object.ReferenceEquals(i, ftt));
Console.WriteLine(System.Object.ReferenceEquals(ftt, obj));
Console.WriteLine(System.Object.ReferenceEquals(i, (int)obj));
Console.WriteLine(System.Object.ReferenceEquals(i, (int)ftt));

上面代码输出如下,至于发生多少次装箱多少次拆箱,你猜?

False
False
False
False
False

转载于:https://www.cnblogs.com/yan7/p/8397696.html

.NET面试题解析(02)-拆箱与装箱相关推荐

  1. 什么是装箱?什么是拆箱?装箱和拆箱的执行过程?

    什么是装箱?什么是拆箱?装箱和拆箱的执行过程?常见问题? 1.什么是装箱?什么是拆箱? 装箱:基本类型转变为包装器类型的过程. 拆箱:包装器类型转变为基本类型的过程. //JDK1.5之前是不支持自动 ...

  2. Java中的拆箱与装箱

    我们先来了解一下拆箱与装箱的概念: 装箱:将基本数据类型转换为包装类: 拆箱:将包装类转换为基本数据类型 我们来看两串代码: Integer b1 = 127;Integer b2 = 127;Sys ...

  3. 第十七节:易混淆的概念(静态和非静态、拆箱和装箱)

    一. 静态和非静态 1. 概念介绍 ① 静态类(被static修饰) vs  普通类(没有被static修饰) ② 静态成员:被static修饰的成员,比如:静态方法.静态字段等 ③ 普通成员(实例成 ...

  4. java double 装箱_Java自动拆箱和装箱

    一.什么是装箱/拆箱 在讲之前,得先提一下为什么两个概念:基本数据类型及其包装类,我们都知道Java是一种面向对象的语言,但是Java中的基本数据类型是不面向对象的,这时在使用中便会存在诸多的不便,为 ...

  5. Java包装类、拆箱和装箱详解

    虽然 Java 语言是典型的面向对象编程语言,但其中的八种基本数据类型并不支持面向对象编程,基本类型的数据不具备"对象"的特性--不携带属性.没有方法可调用. 沿用它们只是为了迎合 ...

  6. 对象包装器与自动(拆箱)装箱+参数数量可变的方法+枚举类

    [0]README 0.1) 本文描述+源代码均 转自 core java volume 1, 旨在理解 自动拆箱(装箱).printf的参数数量可变 以及 枚举类的详细说明: 0.2) 源代码: h ...

  7. java中byte装箱和装箱_Java包装类、拆箱和装箱详解

    虽然 Java 语言是典型的面向对象编程语言,但其中的八种基本数据类型并不支持面向对象编程,基本类型的数据不具备"对象"的特性--不携带属性.没有方法可调用. 沿用它们只是为了迎合 ...

  8. Java知多少(24)包装类、拆箱和装箱详解

    虽然 Java 语言是典型的面向对象编程语言,但其中的八种基本数据类型并不支持面向对象编程,基本类型的数据不具备"对象"的特性--不携带属性.没有方法可调用. 沿用它们只是为了迎合 ...

  9. java装箱和拆箱的意义_java的自动拆箱和装箱是每个程序员都要知道的

    自动装箱和拆箱问题是Java中一个老生常谈的问题了,今天我们就来一些看一下装箱和拆箱中的若干问题.本文先讲述装箱和拆箱最基本的东西. 自动装箱和拆箱从Java 1.5开始引入,目的是将原始类型值转自动 ...

最新文章

  1. 信号与系统课程向学校教务科需要提交的资料
  2. 超大数据下大批量随机键值的查询优化方案 1
  3. python我的世界给予物品指令_我的世界给予物品指令是什么
  4. Django中的反向解析
  5. nfs failed, reason given by server: Permission denied的离奇解决
  6. redis 失效时间单位是秒还是毫秒_Redis有效时间设置及时间过期处理
  7. 抬头遇见图灵奖得主和全球顶尖科学家?超豪华阵容智源大会求带我一个!
  8. 16 分频 32 分频是啥意思_一天一个设计实例任意分频器设计
  9. uni-app微信小程序——商城(6)——我的主页
  10. SQLFeatureNotSupportedException: isValid
  11. 思科服务器如何进入网站,思科路由器怎么进入设置网站
  12. 不要再被骗了------QQ盗号原理大揭秘
  13. influxdb java api使用_InfluxDB使用HTTP的API查询数据
  14. 8、16、32-BIT系列单片机区别与特点
  15. Aerial for Mac(mac最美的鸟瞰屏幕保护程序)支持big
  16. SAP 采购订单入库——移动类型
  17. 吐槽弹幕网,解决映兔源无法播放的书签插件
  18. 使用UltraISO(软碟通)制作U盘启动盘并安装系统
  19. 微信小程序自动化构建(云效)
  20. 利用HbuilderX制作简单网页: HTML5期末大作业——html5漫画风格个人主页

热门文章

  1. lock和synchronized的同步区别与选择
  2. ProcessExplore 最新版
  3. [C++学习历程]基础部分 C++中的函数学习
  4. 单件模式(Singleton Pattern)(转自TerryLee)
  5. 教你分分钟使用Retrofit+Rxjava实现网络请求
  6. spark mllib推荐算法使用
  7. OSCON上最受欢迎的Docker演讲
  8. linux gdb使用
  9. zookeeper windows 下安装
  10. [文档].Altera - Avalon接口规范