首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >关于for循环的再次理解

关于for循环的再次理解

作者头像
PhoenixZheng
发布2018-08-07 16:20:00
5420
发布2018-08-07 16:20:00
举报

先来看一段代码

import java.util.List;
import java.util.Arrays;

public class ForDemo {
    public static void main(String[] args) {
      List<String> sources = Arrays.asList("first", "second", "third");

      for(String str : sources){
        System.out.println(str);
      }
    }
}

这里的 for循环写法是1.5之后引入的新 feature, 允许开发者用简明的方式遍历一个数组中的元素。

这种写法很符合人类思考的方式,如果用 kotlin来写的话从语法上更贴合自然语言的思维,

for(str in sources) {
 ....
}

翻译成自然语言的话, 就是"遍历 sources 中的 str 元素"。

不过关于这种简化写法和我们从接触 java第一天开始就学习的传统 for写法有什么区别呢, 不知道有深入去看过没有。

深入分析

可能很多人已经知道简化写法其实也是通过 Iterator来遍历元素的, 原理很简单, 不过我想用最傻的方式来分析这里面的源码实现, 掌握这种方式以后可以推此至彼,遇到任何问题都能理出一个思路来。

首先我们看一下ForDemo.java编译后的源码是怎样的,

javap -c ForDemo.class

 public class ForDemo {
  public ForDemo();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: iconst_3
       1: anewarray     #2                  // class java/lang/String
       4: dup
       5: iconst_0
       6: ldc           #3                  // String first
       8: aastore
       9: dup
      10: iconst_1
      11: ldc           #4                  // String second
      13: aastore
      14: dup
      15: iconst_2
      16: ldc           #5                  // String third
      18: aastore
      19: invokestatic  #6                  // Method java/util/Arrays.asList:([Ljava/lang/Object;)Ljava/util/List;
      22: astore_1
      23: aload_1
      24: invokeinterface #7,  1            // InterfaceMethod java/util/List.iterator:()Ljava/util/Iterator;
      29: astore_2
      30: aload_2
      31: invokeinterface #8,  1            // InterfaceMethod java/util/Iterator.hasNext:()Z
      36: ifeq          59
      39: aload_2
      40: invokeinterface #9,  1            // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      45: checkcast     #2                  // class java/lang/String
      48: astore_3
      49: getstatic     #10                 // Field java/lang/System.out:Ljava/io/PrintStream;
      52: aload_3
      53: invokevirtual #11                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      56: goto          30
      59: return
}

重点在 #24 行开始, 可以看到这里有 Iterator的方法调用。

关于 Iterator, 我们知道任何继承了 Collection的类都需要默认实现一下 Iterator的接口, 比如 hasNext(), next(),

从源码上来看的话,可以确定的是 for循环也是通过迭代器来实现遍历的, 并且调用了 hasNext和 next方法,

确定了这一点之后就可以猜到,在源码级别的for循环会被编译器优化成下面这样

for(Iterator itr = source.iterator() ; itr.hasNext()) {
    String str = itr.next();
    ....
}

举一反三, 对于任何的Java代码都可以用 javap 的方式来看编译后的机器码, 如果对于某个代码或则语法糖有疑问的话, javap是最简单直接的理解方式。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-05-29,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Android每日一讲 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 深入分析
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档