数组是 Java 中的对象,但它们并不对应于真正的类。实际上,JVM 会在运行中隐式创建数组类,但出于性能原因,它们不是实际的类。
由于它们是对象,因此可以将它们存储在 Object 字段中并像往常一样传递。但是,它们在字节码级别的处理方式略有不同。
首先,使用newarray、anewarray 或multinewarray 指令分别为一维原始数组、一维对象和多维数组创建数组。相比之下,常规对象是使用new 指令创建的。
使用*aload 和*astore 指令完成获取和设置元素。
另外,x.length 不是一个真实的字段。相反,它被编译为arraylength 指令。这可以通过编译以下代码看到。
public void test(int size){
int[] x = new int[size];
String[] y = new String[size];
System.out.println(x.length);
System.out.println(y.length);
}
产生以下字节码
.method public test : (I)V
.limit stack 2
.limit locals 4
iload_1
newarray int
astore_2
iload_1
anewarray java/lang/String
astore_3
getstatic java/lang/System out Ljava/io/PrintStream;
aload_2
arraylength
invokevirtual java/io/PrintStream println (I)V
getstatic java/lang/System out Ljava/io/PrintStream;
aload_3
arraylength
invokevirtual java/io/PrintStream println (I)V
return
.end method
尝试通过手动创建字节码来访问length 字段将导致异常,因为该字段实际上并不存在。
.method static public main : ([Ljava/lang/String;)V
.limit stack 1
.limit locals 1
aload_0
getfield [Ljava/lang/String; length I
return
.end method
结果
Exception in thread "main" java.lang.VerifyError: Expecting reference to class i
n class ArrayTest at constant pool index 30 in method ArrayTest.main([Ljava/lang
/String;)V
at java.lang.Class.getDeclaredMethods0(Native Method)
at java.lang.Class.privateGetDeclaredMethods(Unknown Source)
at java.lang.Class.getMethod0(Unknown Source)
at java.lang.Class.getMethod(Unknown Source)
at sun.launcher.LauncherHelper.getMainMethod(Unknown Source)
at sun.launcher.LauncherHelper.checkAndLoadMain(Unknown Source)