每天一分钟来一颗Java语法糖(二)for-each
Java语法糖for-each
for-each介绍及优点
for-each增强for循环,JDK5.0开始引入,与for对比如下
for | for-each | |
---|---|---|
语法简洁 | √ | |
避免越界 | √ | |
删除元素 | √ | |
替换元素 | √ | |
遍历时索引位置 | √ | |
正向遍历 | √ | √ |
反向遍历 | √ | |
多集合 | √ |
同时,两种遍历方式性能接近。
for-each使用方法
使用参考如下
public class Test {
public static void main(String[] args) {
Set<String> names = new HashSet<>();
names.add("大少");
names.add("二少");
names.add("三少");
for (String name : names) {
System.out.println(name);
}
}
}
执行结果
语法糖原理分析
使用IDEA Show-Bytecode查看执行的字节码
示例代码,为了让分析更容易,避免其他执行带来的干扰,循环中不执行任何其他代码
使用Show-Bytecode查看字节码
public class com/包名隐藏*****/Test2 {
// compiled from: Test2.java
// access flags 0x1
public <init>()V
L0
LINENUMBER 7 L0
ALOAD 0
INVOKESPECIAL java/lang/Object.<init> ()V
RETURN
L1
LOCALVARIABLE this Lcom/包名隐藏*****/Test2; L0 L1 0
MAXSTACK = 1
MAXLOCALS = 1
// access flags 0x9
public static main([Ljava/lang/String;)V
L0
LINENUMBER 9 L0
NEW java/util/HashSet
DUP
INVOKESPECIAL java/util/HashSet.<init> ()V
ASTORE 1
L1
LINENUMBER 10 L1
ALOAD 1
LDC "\u5927\u5c11"
INVOKEINTERFACE java/util/Set.add (Ljava/lang/Object;)Z
POP
L2
LINENUMBER 11 L2
ALOAD 1
LDC "\u4e8c\u5c11"
INVOKEINTERFACE java/util/Set.add (Ljava/lang/Object;)Z
POP
L3
LINENUMBER 12 L3
ALOAD 1
LDC "\u4e09\u5c11"
INVOKEINTERFACE java/util/Set.add (Ljava/lang/Object;)Z
POP
L4
LINENUMBER 13 L4
ALOAD 1
INVOKEINTERFACE java/util/Set.iterator ()Ljava/util/Iterator;
ASTORE 2
L5
FRAME APPEND [java/util/Set java/util/Iterator]
ALOAD 2
INVOKEINTERFACE java/util/Iterator.hasNext ()Z
IFEQ L6
ALOAD 2
INVOKEINTERFACE java/util/Iterator.next ()Ljava/lang/Object;
CHECKCAST java/lang/String
ASTORE 3
L7
LINENUMBER 14 L7
GOTO L5
L6
LINENUMBER 15 L6
FRAME CHOP 1
ALOAD 1
INVOKEINTERFACE java/util/Set.iterator ()Ljava/util/Iterator;
ASTORE 2
L8
FRAME APPEND [java/util/Iterator]
ALOAD 2
INVOKEINTERFACE java/util/Iterator.hasNext ()Z
IFEQ L9
L10
LINENUMBER 16 L10
ALOAD 2
INVOKEINTERFACE java/util/Iterator.next ()Ljava/lang/Object;
POP
GOTO L8
L9
LINENUMBER 18 L9
FRAME CHOP 1
RETURN
L11
LOCALVARIABLE i Ljava/util/Iterator; L8 L9 2
// signature Ljava/util/Iterator<Ljava/lang/String;>;
// declaration: java.util.Iterator<java.lang.String>
LOCALVARIABLE args [Ljava/lang/String; L0 L11 0
LOCALVARIABLE names Ljava/util/Set; L1 L11 1
// signature Ljava/util/Set<Ljava/lang/String;>;
// declaration: java.util.Set<java.lang.String>
MAXSTACK = 2
MAXLOCALS = 4
}
因为Show-Bytecode的便利性,可以直接找到对应行数的字节码
对比L4-L7与L6-L9发现字节码一致。
所以得出,在编译的时候编译器会自动将对for这个关键字的使用转化为对目标的迭代器的使用。