Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/extjs/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Language agnostic 什么是装箱和拆箱,取舍是什么?_Language Agnostic_Boxing_Glossary_Unboxing - Fatal编程技术网

Language agnostic 什么是装箱和拆箱,取舍是什么?

Language agnostic 什么是装箱和拆箱,取舍是什么?,language-agnostic,boxing,glossary,unboxing,Language Agnostic,Boxing,Glossary,Unboxing,我在寻找一个清晰、简洁、准确的答案 理想情况下,作为实际答案,尽管欢迎链接到好的解释。装箱和取消装箱是将原语值转换为面向对象包装类(装箱)的过程,或将值从面向对象包装类转换回原语值(取消装箱)的过程 例如,在java中,如果要将int值存储在集合中,可能需要将其转换为整数(装箱),因为原语不能存储在集合中,只能存储对象。但是,当您想将其从集合中取回时可能需要将值作为int而不是整数来获取,这样您就可以将其取消装箱 装箱和拆箱本身并不坏,但这是一种权衡。根据语言实现的不同,它可能比仅使用原语更慢、

我在寻找一个清晰、简洁、准确的答案


理想情况下,作为实际答案,尽管欢迎链接到好的解释。

装箱和取消装箱是将原语值转换为面向对象包装类(装箱)的过程,或将值从面向对象包装类转换回原语值(取消装箱)的过程

例如,在java中,如果要将
int
值存储在
集合
中,可能需要将其转换为
整数(装箱),因为原语不能存储在
集合
中,只能存储对象。但是,当您想将其从
集合中取回时
可能需要将值作为
int
而不是
整数
来获取,这样您就可以将其取消装箱

装箱和拆箱本身并不坏,但这是一种权衡。根据语言实现的不同,它可能比仅使用原语更慢、内存更密集。但是,它还允许您使用更高级别的数据结构,并在代码中实现更大的灵活性

现在,在Java(和其他语言)“自动装箱/自动取消装箱”特性的上下文中,最常讨论这个问题。这是.Net中的一个

通常,您无法依赖函数将使用的变量类型,因此需要使用从最低公分母扩展而来的对象变量-在.Net中,这是
对象

但是,
对象
是一个类,将其内容存储为引用

List<int> notBoxed = new List<int> { 1, 2, 3 };
int i = notBoxed[1]; // this is the actual value

List<object> boxed = new List<object> { 1, 2, 3 };
int j = (int) boxed[1]; // this is an object that can be 'unboxed' to an int
这很容易解决:

if(c.Equals(d)) // Evaluates to true because it calls the underlying int's equals

if(((int) c) == ((int) d)) // Evaluates to true once the values are cast
但是,在处理装箱值时,另一件事需要小心。

来源:

拳击是铸造价值的行为 键入引用类型:

拆箱是。。。反之:


.NET FCL通用集合:

List<T>
Dictionary<TKey, UValue>
SortedDictionary<TKey, UValue>
Stack<T>
Queue<T>
LinkedList<T>
列表
字典
分类词典
堆栈
队列
链表
都是为了克服以前集合实现中装箱和拆箱的性能问题而设计的

有关更多信息,请参阅第16章。

装箱值是*周围的最小包装。装箱的值通常存储为上对象的指针

因此,装箱的值会占用更多内存,并且至少需要两次内存查找才能访问:一次查找指针,另一次查找指针后的原语。很明显,这不是你想要的内在循环。另一方面,装箱的值通常与系统中的其他类型一起发挥更好的作用。因为它们是该语言中的一流数据结构,所以它们具有其他数据结构所期望的元数据和结构

在Java和Haskell中,泛型集合不能包含未绑定的值。NET中的泛型集合可以保存未绑定的值,而不会受到任何惩罚。其中Java的泛型仅用于编译时类型检查,.NET将

Java和Haskell有未绑定的数组,但它们明显不如其他集合方便。然而,当需要峰值性能时,避免装箱和拆箱的开销是值得的

*在本讨论中,原语值是可以存储在上的任何值,而不是存储为指向堆上值的指针。通常这只是机器类型(int、float等)、结构,有时是静态大小的数组。NET land将其称为值类型(与引用类型相反)。Java人士称之为原始类型。Haskellions只是叫它们unboxed

**在这个回答中,我还将重点放在Java、Haskell和C上,因为这是我所知道的。值得一提的是,Python、Ruby和Javascript都有专门的装箱值。这也被称为“一切都是对象”方法***


***警告:在某些情况下,足够高级的编译器/JIT实际上可以检测到在查看源代码时语义装箱的值在运行时可以安全地成为未装箱的值。本质上,多亏了出色的语言实现者,您的箱子有时是免费的。

与其他任何东西一样,如果不小心使用,自动装箱可能会有问题。经典的做法是以一个NullPointerException结束,而无法找到它。即使有调试器。试试这个:

public class TestAutoboxNPE
{
    public static void main(String[] args)
    {
        Integer i = null;

        // .. do some other stuff and forget to initialise i

        i = addOne(i);           // Whoa! NPE!
    }

    public static int addOne(int i)
    {
        return i + 1;
    }
}

装箱
是将值类型转换为引用类型的过程。而
取消装箱
是将引用类型转换为值类型

EX: int i = 123;
    object o = i;// Boxing
    int j = (int)o;// UnBoxing
int i=123;
object o=(object)i; //Boxing

o=123;
i=(int)o; //Unboxing.
值类型有:
int
char
结构
枚举
。 参考类型包括:
接口
数组
字符串
对象
装箱和取消装箱有助于将值类型视为对象。装箱意味着将值转换为对象引用类型的实例。例如,
Int
是一个类,
Int
是一个数据类型。将
int
转换为
int
是装箱的一个示例,而将
int
转换为
int
则是取消装箱。这个概念有助于垃圾收集,另一方面,取消装箱将对象类型转换为值类型

EX: int i = 123;
    object o = i;// Boxing
    int j = (int)o;// UnBoxing
int i=123;
object o=(object)i; //Boxing

o=123;
i=(int)o; //Unboxing.

这只是一段糟糕的代码,与自动装箱无关。变量
i
过早初始化。要么将其设置为空声明(
Integer i;
),这样编译器就可以指出您忘记初始化它,要么等待声明它,直到您知道它的值。嗯,如果我在try-catch块中执行某些操作,那么编译器将强制我使用某些东西初始化它。这不是真正的代码-这是一个如何发生的示例。这说明了什么?绝对没有理由使用Integer对象。现在,您必须处理一个潜在的空指针。为什么虽然是一个装箱值,但CLR或其他任何形式的装箱值有什么好处呢
int i=123;
object o=(object)i; //Boxing

o=123;
i=(int)o; //Unboxing.