我知道当我使用关键字调用其构造函数时会创建一个array
对象:Java
new
int[] myIntArray = new int[3];
但如果我改为写
int[] myIntArray = {1,2,3};
创建了一个array
对象,但我没有用new
. 这在底层是如何工作的——如何在不调用构造函数的情况下在 Java 中创建对象?
我知道当我使用关键字调用其构造函数时会创建一个array
对象:Java
new
int[] myIntArray = new int[3];
但如果我改为写
int[] myIntArray = {1,2,3};
创建了一个array
对象,但我没有用new
. 这在底层是如何工作的——如何在不调用构造函数的情况下在 Java 中创建对象?
就创建数组对象而言,它是语法糖。编译后,它的工作方式与标准语法完全相同。
不过这里的不同之处在于,在第一个版本中,您没有填充数组 - 所有元素都是 的默认值int
,即 0。
在第二个版本中,您正在创建和填充数组。
这部分:
{1,2,3}
是一个数组初始值设定项,可用作声明的一部分。引用JLS,第 10.6 节:
数组初始值设定项可以在声明中指定(第 8.3 节、第 9.3 节、第 14.4 节),或者作为数组创建表达式的一部分(第 15.10 节)来创建数组并提供一些初始值。
ArrayInitializer: { VariableInitializersopt ,opt }
两种说法都是一样的。第二条语句 int[] myIntArray = {1,2,3}; 是使用新方法的语法的捷径。
int[] myIntArray ={1,2,3} ,这种情况下数组的长度由大括号之间提供的值的数量决定,并用逗号分隔。
获取这段代码并编译它:
public class ArrayTest {
public static void main1() {
int[] array = new int[3]; array[0] = 10; array[1] = 20; array[3] = 30;
}
public static void main2() {
int[] array = new int[] {10, 20, 30};
}
public static void main3() {
int[] array = {10, 20, 30};
}
}
然后使用javap -c
反汇编查看其字节码,得到如下结果。但是您会看到后面的两个片段或方法编译为相同的字节码。所以int[] array = new int[] {1, 2, 3}
和int[] array = {1, 2, 3}
都是一样的。但是单独创建一个数组并为其每个元素分配值的处理方式不同,因此后面的两个片段不是第一个片段的语法糖。
$ javap -c ArrayTest
Compiled from "ArrayTest.java"
public class ArrayTest extends java.lang.Object{
public ArrayTest();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: return
public static void main1();
Code:
0: iconst_3
1: newarray int
3: astore_0
4: aload_0
5: iconst_0
6: bipush 10
8: iastore
9: aload_0
10: iconst_1
11: bipush 20
13: iastore
14: aload_0
15: iconst_3
16: bipush 30
18: iastore
19: return
public static void main2();
Code:
0: iconst_3
1: newarray int
3: dup
4: iconst_0
5: bipush 10
7: iastore
8: dup
9: iconst_1
10: bipush 20
12: iastore
13: dup
14: iconst_2
15: bipush 30
17: iastore
18: astore_0
19: return
public static void main3();
Code:
0: iconst_3
1: newarray int
3: dup
4: iconst_0
5: bipush 10
7: iastore
8: dup
9: iconst_1
10: bipush 20
12: iastore
13: dup
14: iconst_2
15: bipush 30
17: iastore
18: astore_0
19: return
在底层,两种初始化数组的方法是相同的。
再举一个例子,看看这个:
String str = "Hello"; // no 'new' statement here
String str = new String("Hello");
两种语句都做同样的事情,但一种比另一种方便得多。但在引擎盖下,它们在编译后几乎做同样的事情。