一些数据类型被认为是“原始的”,意思是它们不像对象一样被处理,也没有对象的属性。
在大多数平台上,整数和字符是原始类型的例子,但可以进行装箱(boxing)。
装箱指将它们包装在一个对象中,以便它们具有对象的行为。
确切的含义和行为取决于所使用的语言。有些语言(比如 Smalltalk……至少在我做的时候是这样的)不允许任何原始类型,并将所有东西都视为对象,但这会带来性能损失,因为归根结底,处理器需要使用原始数字和原始内存来进行有效工作。例如,如果要添加两个被装箱的整数,则其后台会“取消装箱”成原始类型,将数字相加,然后又装箱成一个新的整数。
更具体的Java信息:
自动装箱允许Java在大多数情况下自动将像boolean
和int
这样的东西转换为它们的对象版本Boolean
和Integer
。 它也允许反向发生。
例如:
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);
是的,装箱意味着将值类型包装在引用类型中。自从Java引入了自动装箱,你可以这样做:
void foo(Object bar) {}
//...
foo(1);
Java会自动将整数1转换为Integer类型。在之前的版本中,您需要执行以下操作:
foo(new Integer(1));
在Java中,自动装箱最常用于使用泛型时,因为你无法使用原始类型与泛型一起工作。所以,如果要将 int 存储在列表中,你需要创建一个 List<Integer>
并将 int 包装成 Integer 对象放入列表中。
Boxed类型意味着值在堆上分配,并通过指针引用。这对于运行时实现的统一性非常有好处(它使得具有通用函数等更容易),但代价是需要额外的间接引用。
Boxed 意味着将一个普通的值类型放在一个对象中。有点像把它装在盒子里。一般来说,应该避免这样做,因为构造对象的开销较大。