创建数组与访问数组元素

创建数组与访问数组元素

数组的创建和访问也是我们编程中经常用到的。在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指令。