1.数组
数组是JVM内置的一种对象类型,这个对象同样是继承的Object类。我们使用代码来理解一下
/**
* @author 公众号:三明治聊IT
* @date 2021/6/13
*/
public class ArrayDemo {
int getValue() {
int[] arr = new int[]{1111,2222,3333,4444};
return arr[2];
}
int getLength(int[] arr) {
return arr.length;
}
}
1.1 数组创建
可以看到,新建数组的代码,被编译成了newarray指令
newarray 10 (int)
数组里的初始化内容,被顺序编译成了一系列指令放入:
- sipush 将一个短整型常量值推送至栈顶;
-
iastore 将栈顶int型数值存入指定数组的指定索引位置。
具体操作:
1.dup, 索引数组下标
2.iconst_0, 常量0,入操作数栈
3.sipush, 将一个常量1111加载到操作数栈
4.将栈顶int型数值存入数组0索引位置
为了支持多种类型,从操作数栈存储到数组,有更多的指令:bastore、castore、sastore、iastore、lastore、fastore、dastore、aastore。
1.2 数组访问
数组元素的访问,是通过第28~30行代码来实现的
- aload_1 将第二个引用类型本地变量推送至栈顶,这里是生成的数组
- iconst_2 将int型2推送至栈顶
- iaload 将int型数组指定索引的值推送至栈顶
获取数组的长度,是由字节码指令arraylength来完成的
2 遍历
无论是Java的数组,还是List,都可以使用foreach语句进行遍历,虽然在语言层面它们的表现形式是一致的,但实际实现的方法并不同。
import java.util.List;
/**
* @author 公众号:三明治聊IT
* @date 2021/6/14
*/
public class ForLoopDemo {
void loop(int[] arr) {
for (int i : arr) {
System.out.println(i);
}
}
void loop(List<Integer> list) {
for (int i : list) {
System.out.println(i);
}
}
}
数组:它将代码解释成了传统的变量方式,即for(int i;i<length;i++) 的形式。
List: 它实际是把list对象进行迭代并遍历的,在循环中,使用了Iterator.next()方法。
使用jd-gui反编译工具,可以看到实际生成的代码:
再看这两个的字节码
loop数组的字节码:
0 aload_1
1 astore_2
2 aload_2
3 arraylength
4 istore_3
5 iconst_0
6 istore 4
8 iload 4
10 iload_3
11 if_icmpge 34 (+23)
14 aload_2
15 iload 4
17 iaload
18 istore 5
20 getstatic #2 <java/lang/System.out>
23 iload 5
25 invokevirtual #3 <java/io/PrintStream.println>
28 iinc 4 by 1
31 goto 8 (-23)
34 return
loop list的字节码:
0 aload_1
1 invokeinterface #4 <java/util/List.iterator> count 1
6 astore_2
7 aload_2
8 invokeinterface #5 <java/util/Iterator.hasNext> count 1
13 ifeq 39 (+26)
16 aload_2
17 invokeinterface #6 <java/util/Iterator.next> count 1
22 checkcast #7 <java/lang/Integer>
25 invokevirtual #8 <java/lang/Integer.intValue>
28 istore_3
29 getstatic #2 <java/lang/System.out>
32 iload_3
33 invokevirtual #3 <java/io/PrintStream.println>
36 goto 7 (-29)
39 return