什么是“装箱类型”?

74
我听说有些语言中会将类型称为“boxed”。在Java中,我听说过“自动装箱”(autoboxing)。这是什么?它是否为一种为类型提供包装类的机制?如果我使用“boxed”或“unboxed”类型进行编码,我的代码会如何改变?
6个回答

92

一些数据类型被认为是“原始的”,意思是它们不像对象一样被处理,也没有对象的属性。

在大多数平台上,整数和字符是原始类型的例子,但可以进行装箱(boxing)。

装箱指将它们包装在一个对象中,以便它们具有对象的行为。

确切的含义和行为取决于所使用的语言。有些语言(比如 Smalltalk……至少在我做的时候是这样的)不允许任何原始类型,并将所有东西都视为对象,但这会带来性能损失,因为归根结底,处理器需要使用原始数字和原始内存来进行有效工作。例如,如果要添加两个被装箱的整数,则其后台会“取消装箱”成原始类型,将数字相加,然后又装箱成一个新的整数。


33

更具体的Java信息:

自动装箱允许Java在大多数情况下自动将像booleanint这样的东西转换为它们的对象版本BooleanInteger。 它也允许反向发生。

例如:

int a = 3; // no boxing is happening
Integer b = 3;  // newer versions of java automatically convert the int 3 to Integer 3
int c = b;  // these same versions also automatically convert Integer 3 to int 3

旧版本的Java不支持自动装箱,因此需要使用以下代码来完成相同的操作:

int a = 3;  // works the same
Integer b = new Integer(3);  //must set up a Integer object manually
int c = b.intValue(); //must change Integer object to a primitive

然而,有些情况下您仍需手动完成一些工作。例如,假设您有一个类,其中包含两个方法:

assertEquals(int a, int b);
assertEquals(Object a, Object b)

现在,如果你尝试这样做:

Integer a = 3;
int b = 3;
assertEquals(a, b);  // this will not compile

这不起作用的原因是因为它无法确定是否应该将a解包成int还是将b装箱成Integer。因此,无法确定应调用哪个方法签名。要解决这个问题,您可以执行以下操作之一:

assertEquals((int) a, b);
assertEquals(a, (Integer) b);

很棒的演示和例子! - kgui

13

是的,装箱意味着将值类型包装在引用类型中。自从Java引入了自动装箱,你可以这样做:

void foo(Object bar) {}
//...
    foo(1);

Java会自动将整数1转换为Integer类型。在之前的版本中,您需要执行以下操作:

foo(new Integer(1));

在Java中,自动装箱最常用于使用泛型时,因为你无法使用原始类型与泛型一起工作。所以,如果要将 int 存储在列表中,你需要创建一个 List<Integer> 并将 int 包装成 Integer 对象放入列表中。


5

Boxed类型意味着值在堆上分配,并通过指针引用。这对于运行时实现的统一性非常有好处(它使得具有通用函数等更容易),但代价是需要额外的间接引用。


2

Boxed 意味着将一个普通的值类型放在一个对象中。有点像把它装在盒子里。一般来说,应该避免这样做,因为构造对象的开销较大。


1
通常在处理集合时,您正在处理对象数组。在像Java这样的语言中,原始类型和对象之间有区别。当一个原始类型被“装箱”时,它实际上只是一个原始类型的包装器,因此它可以与期望一个对象的框架很好地协作。
自动装箱只是将原始类型放入对象或透明地从对象中取出原始类型的行为,因此您不必担心自己要做的额外步骤。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接