为什么有些语言需要拳击和拆箱?

Ara*_*raK 30 c++ java generics boxing unboxing

这不是什么是装箱和拆箱的问题,而是为什么像Java和C#这样的语言需要呢?

我非常熟悉C++,STL和Boost.

在C++中,我可以很容易地写出这样的东西,

std::vector<double> dummy;
Run Code Online (Sandbox Code Playgroud)

我有一些Java经验,但我真的很惊讶,因为我必须写这样的东西,

ArrayList<Double> dummy = new ArrayList<Double>();
Run Code Online (Sandbox Code Playgroud)

我的问题,为什么它应该是一个对象,在谈论泛型时,在技术上如此难以包含原始类型?

Jul*_*anR 50

在谈论泛型时,在技术上如此难以包含原始类型?

在Java的情况下,这是因为泛型的工作方式.在Java中,泛型是一种编译时技巧,可以防止您将Image对象放入ArrayList<String>.但是,Java的泛型是使用类型擦除实现的:泛型类型信息在运行时丢失.这是出于兼容性原因,因为在Java的生命中添加了泛型.这意味着,运行时,a ArrayList<String>实际上是一个ArrayList<Object>(或更好的:只是ArrayList预期并Object在其所有方法中返回),它会String在您检索值时自动转换为.

但由于int没有从派生Object,你不能把它放在预期(在运行时)一个ArrayList Object,你不能施放Objectint无论是.这意味着int必须将原语包装到一个继承的类型中Object,例如Integer.

例如,C#的工作方式不同.C#中的泛型也在运行时强制执行,并且不需要装箱List<int>.只有当您尝试存储类似于int引用类型变量的值类型时,才会发生C#中的Boxing object.因为int在C#中继承Object了C#,所以写入object obj = 2是完全有效的,但是int将被装箱,这由编译器自动完成(没有Integer引用类型暴露给用户或任何东西).


And*_*are 12

拳击和拆箱是必不可少的,因为语言(如C#和Java)实现了他们的内存分配策略.

某些类型在堆栈上分配,而其他类型在堆上分配.为了将堆栈分配的类型视为堆分配类型,需要装箱以将堆栈分配的类型移动到堆上.拆箱是相反的过程.

在C#中,栈分配的类型称为值类型(例如System.Int32System.DateTime),而堆分配的类型称为引用类型 (例如System.StreamSystem.String).

在某些情况下,能够将值类型视为参考类型(反射是一个示例)是有利的,但在大多数情况下,最好避免装箱和拆箱.

  • 小心值类型和基于堆栈的分配.Eric Lippert在这个主题上有两篇很棒的博客文章:http://blogs.msdn.com/ericlippert/archive/2009/04/27/the-stack-is-an-implementation-detail.aspx和http:// blogs .msdn.com/ericlippert /存档/ 2009/05/04 /的堆叠-是-AN-实现的细节部分two.aspx (4认同)
  • AFAIK,C#不会在通用容器上使用自动装箱,除非您指定类似List <object>的内容.C#的泛型以类似于C++的方式工作于值类型.http://msdn.microsoft.com/en-us/library/ms379564(VS.80).aspx (3认同)