上一遍留下来一个题目:1.ToString() 有没有装箱,答案是没有
从以下几点来解释:
首先确认什么是值类型和引用类型:所有书和你说
值类型:放置在栈上
引用类型:放置在堆上
但是想下 List<int> 中的 值 到底存放在堆上 还是栈上,所以我这边拆分成5个点来梳理:
1. 单独使用场景 如 void a(){in i = 0; Object o = new Object()};
首先明确一点,所有的方法都是 以IL代码执行,
所以首先将此IL代码加载到栈上,注意:是整个 IL 代码都直接 以方法的维度直接加载到栈上
其次 执行到 int i= 0; 会直接在栈上分配 4个字节32位来将 0 加载到 栈上,而不需要在堆上分配内存,当此方法使用完成,会直接丢失掉,除非又加载到 其他栈上,这个就是 栈上IL代码直接分配 基础类型.
而 Object 0 = new Object,需要在堆上分配内存,然后把地址加载到栈上,每次使用的时候,通过引用地址来操控.
也就是 去堆上分配地址,将地址返回到栈上,操作值的时候 先通过地址在堆上找到值,加载到栈上反反复复操作
简单说:
2. 联合使用场景 如 void a(){in i = 0;List<i> list = new List<int>().Add(i)};
首先也是加载IL代码
其次正常执行基本类型在栈上分配
然后执行对象类型在堆上分配
最关键的点是 .Add(1) 中1 如何分配值的.
答案:在堆上分配连续的内存保存 1 的值, 那这时候 Add(1) 与1 有什么区别.
其实没区别,只不过保存的地方不一样.生命周期不一样,最终 在使用的点都是 加载到栈上 完全一致,
只不过在堆上是通过地址找到此值加载到栈上,
3. 联合使用场景 如
void a(){
List<i> list = new List<int>().Add(1);
List<Object> list = new List<Object>().Add(new Object());
};
相同的点 就跳过.
堆上分配 1 与 new Object() 有什么不同?
多了几个步骤:
分配 1 就直接 分配4个字节即可
new Object() 首先 去找Object 类型,找到去加载,没找到 得先创造 Object 类型(注意 Object对象 和 Object 类型不一样,一个是 Object对象, 一个是 Type对象,名字是 Object),找到了 在堆上首先关联 Object类型对象信息,再去创造 同步块索引(这就是 lock 能够 出现锁的原因,全局唯一凭证)
总结:
1 和 Object 实质都是地址,只不过 1 只需要分配 4个字节即可, new Object() 首先去全局查 Object类型对象,没有还得全局加锁 毕竟类型对象也是全局加锁,在去全局创造同步块索引,在去分配内部空间。
所以 也就是因为 引用类型的巨大开销,为了复用,所以放置在堆上,而不是每次重新创造。
并不是 栈和堆的明显不同,也并不是 1和 Object 分配地址不同。只不过 Object 需要分配更多的数据 和 空间
首先分配 object地址,然后计算 Object 类型对象信息, 再去创造同步块索引, 在去 分配4个字节保存 1
其他2个开销才是最大的开销,而不是 栈 和 堆 上速度不同导致的 结果
PS: 针对类型对象信息 和 同步块索引 也有优化
1. 同步块索引已经优化到 只有在使用的时候 (如lock)才去创造,而不是每次都去
2. 类型对象信息 只要加载就不会GC,全局持有
总结下来就是: 1. 如果是基本类型在使用的时候栈上直接分配,引用类型在堆上分配
2. 如果List<i> 在堆上使用基本类型 只需要分配地址即可,但是引用类型不仅需要分配地址,还得分配同步块索引,类型对象信息。
3.int a = 1; Object b = 1;中 a只需要4个字节长度, b 需要先分配4个字节,然后分配类型对象信息8个字节,同步块索引8位,并且类型对象信息和同步块索引如果创建的时候是全局单一的。
所以这就是装箱的巨大开销。但是拆箱其实没啥开销,就是在栈上分配地址将值加载进来即可
上面沟通了,只有在堆上 且 分配了类型对象信息及同步块索引才是装箱
那 1.ToString()是否分配了类型对象信息。也就是指向了 Integate 类型对象信息?
答案 是无,
那怎么输出了 “1”?
原因是 调用了 IL底层代码,没有去堆上找其类型对象信息去调用
所以这就是大家疑惑的点,也是我以前疑惑的点。
就和 thinking in java说的,JAVA一切皆为对象,但是后面少了一句不属于JAVA的不算对象
所以总结下来就是:
一切希望通过类型对象信息找方法或者实现的 都需要装箱 如 Object i= 1;ValueType i=1; 1.equals(1);
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。