我读过这篇文章:int是Java中的对象吗?。
文章认为int
不是从Object
继承来的。如果是这样的话,那么为什么下面的代码编译时没有任何错误呢?假设int
不是Object
,并且format()
方法的签名是public static String format(String format, Object... args)
,如文档所示:javadoc for String!
public class Testing {
public static void main(String[] args) {
int integer = 7;
String str = String.format("%03d", integer);
System.out.println(str);
}
}
我也读过关于";自动装箱";。这到底意味着什么?在编译之前,是否所有的基元都被适当的Object
替换?如果是这样的话,那么在使用int
(int[]
)的大阵列而不是Integer
(Integer[]
)时,内存使用有什么优势吗?类似的论点也适用于double's等
欢迎任何见解。
它是由Autoboxing引起的。
以下是链接的Java文档中的一个小片段,它比我所能解释的更好:
Autoboxing是Java编译器进行的自动转换在基元类型及其对应的对象包装器之间类。例如,将int转换为Integer,将double转换为加倍,依此类推。如果转换为另一种方式,则为称为开箱。
以下是自动装箱的最简单示例:
Character ch = 'a';
本节中的其余示例使用泛型。如果你不是熟悉泛型的语法,请参阅泛型(更新版)课程
考虑以下代码:
List<Integer> li = new ArrayList<>();
for (int i = 1; i < 50; i += 2)
li.add(i);
尽管您将int值添加为基元类型,而不是整数对象,到李,代码编译。因为李是Integer对象,而不是int值的列表,您可能想知道为什么Java编译器不会发出编译时错误。编译器没有生成错误,因为它从i创建Integer对象并添加对象转换为li。因此,编译器将以前的代码转换为运行时如下:
List<Integer> li = new ArrayList<>();
for (int i = 1; i < 50; i += 2)
li.add(Integer.valueOf(i));
调用String.format("%d",myInt)
时,myInt
自动(隐式)包装在Integer
实例中,该实例扩展了Object
,因此它进行编译。
关于阵列,由于某种原因,从primitiveType[]
到WrapperClass[]
的转换不是自动的。如果您试图使用一个基元类型的数组,其中需要包装类的数组,则会导致编译错误。
与使用int
相比,使用Integer
会产生开销,因为您需要分配和存储引用。然而,当使用-128和127之间的Integer
值时,这种开销是有限的,因为这些值是池化的(这意味着在该时间间隔中包装值的Integer
的所有实例都指向unic引用)。
Autoboxing是编译器的帮助,它可以自动编译类似的东西
foo(i);
进入
foo(Integer.valueOf(i));
当foo()
接受Object类型的参数并向其传递基元类型(在本例中为int)时。它只是使代码更易于键入和阅读。
这就是这里发生的事情。String.format()
方法需要对象作为参数。您正在向它传递一个基元类型,因此编译器会自动将它框为Integer。