每天一分钟来一颗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这个关键字的使用转化为对目标的迭代器的使用。

原创文章 29 获赞 41 访问量 948

猜你喜欢

转载自blog.csdn.net/lovesunren/article/details/105803225