原 荐 你真的了解For循环吗?一道For循

疑问

最近群友抛出了一个面试题,就是下图中的第二题,是关于一个for循环的执行结果的问题,他的代码的执行结果是什么呢? 

代码复现

下面的例子和面试题上面的大同小异,是个非常简单的例子。首先这个代码是可以编译通过的,也可以正常执行的。那么执行结果是什么呢?会跟我们猜想的一样吗?

/**
 * Created by baiguantao on 2017/10/20.
 */
public class T {
    public  static boolean  testA(char a){
        System.out.print(a);
        return true;

    }

    /**
     * for循环的一些疑问
     * @param args
     */
    public static void main(String[] args) {
        int i=0;
        for (testA('a');testA('b')&&(i<2);testA('c')) {
            i++;
            testA('d');
        }
    }
}
  • 执行结果

abdcbdcb

那么问题来了,为什么是这个结果呢?我们可以借助javap命令反编译我们刚才编译的T.class进行分析。 如果对jvm不了解的可以参阅JVM基础

反编译

  • 先贴出原版的字节码反编译后的代码,后边会对反编译的文件进行逐行解析,那么我们先来看看上述类反编译后的样子吧。如下所示:
C:\Users\temp\IdeaProjects\mix_learn\target\classes>javap -c T.class
Compiled from "T.java"
public class T {
  public T();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static boolean testA(char);
    Code:
       0: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
       3: iload_0
       4: invokevirtual #3                  // Method java/io/PrintStream.print:(C)V
       7: iconst_1
       8: ireturn


  public static void main(java.lang.String[]);
    Code:
       0: iconst_0
       1: istore_1
       2: bipush        97
       4: invokestatic  #4                  // Method testA:(C)Z
       7: pop
       8: bipush        98
      10: invokestatic  #4                  // Method testA:(C)Z
      13: ifeq          39
      16: iload_1
      17: iconst_2
      18: if_icmpge     39
      21: iinc          1, 1
      24: bipush        100
      26: invokestatic  #4                  // Method testA:(C)Z
      29: pop
      30: bipush        99
      32: invokestatic  #4                  // Method testA:(C)Z
      35: pop
      36: goto          8
      39: return
}
  • 说明版本

对反编译后的文件是不是一脸懵逼,没太看懂是什么意思呢?没关系,下面我们进行逐行分析。

C:\Users\temp\IdeaProjects\mix_learn\target\classes>javap -c T.class
Compiled from "T.java"
public class T {
  public T(); // 这里是默认生成的无参构造函数部分开始
    Code:
       0: aload_0                           //表示对this的操作
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V   调用特殊实例方法
       4: return                            // 返回结果 
                    // 这里是默认生成的无参构造函数部分结束
  public static boolean testA(char);// 这里是我们写入的静态方法
    Code:
       0: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;   System.out调用类方法
       3: iload_0                           //从局部变量表中加载int型的数据到操作数栈
       4: invokevirtual #3                  // Method java/io/PrintStream.print:(C)V  调用实例方法
       7: iconst_1                          //int类型0进栈 
       8: ireturn                           // 返回结果

  public static void main(java.lang.String[]);
    Code:
       0: iconst_0                          //int类型0进栈 
       1: istore_1                          // int类型1出栈
       2: bipush        97                  // byte型常量97(a)进栈
       4: invokestatic  #4                  // Method testA:(C)Z  执行静态方法testA
       7: pop                               // 栈顶数值出栈(不能是long/double)
       8: bipush        98                  // byte型常量98(b)进栈
      10: invokestatic  #4                  // Method testA:(C)Z  执行静态方法testA
      13: ifeq          39                  //判断语句  是否相等  循环结束 跳转到39
      16: iload_1                           //从局部变量表中加载int型的数据到操作数栈
      17: iconst_2                          //int类型2进栈 
      18: if_icmpge     39                  //比较栈顶两int型数值大小,当结果大于等于0时跳转到39的位置 
      21: iinc          1, 1                //给局部变量表的1号位置的int值增加1
      24: bipush        100                 // byte型常量100(d)进栈 
      26: invokestatic  #4                  // Method testA:(C)Z  执行静态方法testA
      29: pop                               // 栈顶数值出栈(不能是long/double)
      30: bipush        99                  // byte型常量99(c)进栈 
      32: invokestatic  #4                  // Method testA:(C)Z 执行静态方法testA
      35: pop                               // 栈顶数值出栈(不能是long/double)
      36: goto          8                   // 重新循环 到8的位置
      39: return                            //退出循环
}
  • 流程图

整体上的结构

for循环执行流程

总结

从反编译文件以及流程图中我们可以看出for循环执行的顺序是:

  • testA(a)
  • testA('b')
  • testA('d')
  • testA('c')
  • testA('b')
  • testA('d')
  • testA('c')
  • testA('b')

所以我们的执行输出结果是:abdcbdcb

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏架构师小秘圈

你真的了解For循环吗?一道For循环Java面试题引发的思考

一,疑问 最近群友抛出了一个面试题,就是下图中的第二题,是关于一个for循环的执行结果的问题,他的代码的执行结果是什么呢? ? 二,代码复现 下面的例子和面试...

2716
来自专栏Gaussic

一个关于Java输入输出优化的坑 原

在用Scanner输入大量数据的时候,会出现时间巨慢的问题,今天网上查到了方法,原来java的输入输出是有优化方法的。

481
来自专栏牛肉圆粉不加葱

Spark Streaming Failed to read checkpoint from directory ...现象解决方案及原因

使用spark-submit提交一个Spark Streaming Application至yarn集群, 报错

822
来自专栏拭心的安卓进阶之路

Java 集合深入理解(4):List<E> 接口

蓝瘦!香菇! 连着加班几天,醉了。学学 List 放松下! ? 在 Java 集合深入理解:Collection 中我们熟悉了 Java 集合框架的基本概念和...

21510
来自专栏Android 研究

Android JNI学习(三)——Java与Native相互调用

前面两篇文章简单的介绍了JNI,下面我们就进一步了解下一下JNI的调用原则,要想了解JNI的调用原则, 前面我们说了JNI中的JNIEnv以及Java类型和na...

853
来自专栏Python爬虫与算法进阶

top k frequent words(前K个高频单词)

返回的答案应该按单词出现频率由高到低排序。如果不同的单词有相同出现频率,按字母顺序排序。

992
来自专栏一个会写诗的程序员的博客

《Kotlin 极简教程 》第5章 集合类(1)

本章将介绍Kotlin标准库中的集合类,我们将了解到它是如何扩展的Java集合库,使得写代码更加简单容易。如果您熟悉Scala的集合库,您会发现Kotlin跟S...

792
来自专栏Java爬坑系列

【Java入门提高篇】Day27 Java容器类详解(九)LinkedList详解

  这次介绍一下List接口的另一个践行者——LinkedList,这是一位集诸多技能于一身的List接口践行者,可谓十八般武艺,样样精通,栈、队列、双端队列、...

633
来自专栏王硕

原 pg查询树的简单解读

34113
来自专栏开发 & 算法杂谈

JNI基础知识学习汇总

JNI(Java Native Interface),也就是java本地接口,主要是用来支持和本地代码之间的互动-在Java程序中调用native code或者...

1995

扫码关注云+社区