创建数组与访问数组元素
创建数组与访问数组元素
数组的创建和访问也是我们编程中经常用到的。在java中,如果访问一个数组的索引超过数组的大小,会被虚拟机检测到,并抛出数组越界异常,这是因为在虚拟机执行访问数组的指令时,数组的大小已经是确定的,可以在执行指令之前检测索引是否超过数组大小。我们分基本数据类型数组、引用类型数组两种不同的数组,分别看下如何在字节码层面实现创建数组与访问数组元素。
基本数据类型数组
基本数据类型的数组创建与访问如代码清单3-31所示。
代码清单3-31 基本数据类型的数组创建与访问
public static void baseArray() { int[] array = new int[2]; array[1] = 100; int a = array[1]; }
使用javap命令输出baseArray方法的字节码如下。
public static void baseArray(); Code: 0: iconst_2 1: newarray int 3: astore_0 4: aload_0 5: iconst_1 6: bipush 100 8: iastore 9: aload_0 10: iconst_1 11: iaload 12: istore_1 13: return
偏移量为0和1的字节码指令完成数组的创建,iconst_2指令设置数组的大小为2,将立即数2放入操作数栈顶,newarray指令需要一个操作数,操作数占一个字节,如创建int类型的数组则操作数的值为10,创建long类型的数组则操作数为11等。
偏移量为4、5、6、8的这四条指令分别是将数组引用放入操作数栈顶、将访问数组的索引1放入操作数栈顶、将立即数100放入栈顶、最后iastore指令将栈顶int类型值100保存到int类型数组的索引为1的位置。偏移量为9、10、11这三条指令是读取int类型数组索引为1的元素放入操作数栈的栈顶,iaload指令将int类型数组指定索引位置处的元素放入操作数栈的栈顶。
iaload指令和iastore指令都不需要操作数。iastore指令执行之前,要求当前操作数栈必须存在int类型数组的引用、访问数组的索引、将要赋给数组元素的值,这三项是按顺序入栈的。iaload指令执行之前,要求当前操作数栈必须存在int类型数组的引用、访问数组的索引,按顺序入栈,返回值存放在操作数栈的栈顶。
访问基本数据类型数组的指令还有,对应long类型的laload和lastore指令,对应float类型的faload和fastore指令,对应double类型的daload和dastore指令,对应char类型的caload和castore指令,对应short类型的saload和sastore指令。如表3-33所示。
表3-33 基本数据类型数组访问指令表


引用类型数组
引用类型数组的创建与访问如代码清单3-34所示。
代码清单3-34引用类型的数组创建与访问
public static void objArray(){ User[] users = new User[2]; users[0] = new User(); users[1] = users[0]; }
使用javap命令输出objArray方法的字节码如下。
public static void objArray(); Code: 0: iconst_2 1: anewarray #2 // class com/wujiuye/asmbytecode/book/third/model/User 4: astore_0 5: aload_0 6: iconst_0 7: new #2 // class com/wujiuye/asmbytecode/book/third/model/User 10: dup 11: invokespecial #3 // Method com/wujiuye/asmbytecode/book/third/model/User."<init>":()V 14: aastore 15: aload_0 16: iconst_1 17: aload_0 18: iconst_0 19: aaload 20: aastore 21: return
与访问基本数据类型数组的逻辑差不多,创建数组使用的是anewarray指令,获取数组指定索引位置处的元素使用aaload指令,将对象的引用写到数组指定索引位置处使用aastore指令。引用类型数组访问指令如表3-36所示。
表3-36 引用类型数组访问指令表

创建数组的指令如表3-37所示。
表3-37 创建数组的指令表

访问数组的字节码指令还有获取数组一维长度的arrayleng指令,创建多维度的数组指令multinewarray指令。