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

转载 2017年11月18日 00:00:00
一,疑问

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

640?wx_fmt=png&wxfrom=5&wx_lazy=1


二,代码复现

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

/**
 * 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: returnpublic 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 //退出循环
}
  • 流程图

整体上的结构:

0?wx_fmt=png

for循环执行流程

0?wx_fmt=png

四,总结

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

  • testA(a)

  • testA('b')

  • testA('d')

  • testA('c')

  • testA('b')

  • testA('d')

  • testA('c')

  • testA('b')

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

五,最后

本次投稿作者:ricky,java领域专家!

更多精彩,请戳除破这里:https://my.oschina.net/lt0314

推荐阅读:2T架构师教学视频分享

0?wx_fmt=png0?wx_fmt=png

架构师小秘圈,聚集10万架构师的小圈子!不定期分享技术干货,行业秘闻!汇集各类奇妙好玩的话题和流行动向!长按左侧图片,扫码加入架构师微信群!

用9种办法解决 JS 闭包经典面试题之 for 循环取 i

闭包 正确的说,应该是指一个闭包域,每当声明了一个函数,它就产生了一个闭包域(可以解释为每个函数都有自己的函数栈),每个闭包域(Function 对象)都有一个 function scope...
  • u013243347
  • u013243347
  • 2016年08月06日 10:11
  • 1961

Java 循环语句练习题(1)

1、for循环输出1 到100package com.hz.loop;/** * 1、for循环输出1 到100 * @author ztw * */ public class Practic...
  • qq_33624284
  • qq_33624284
  • 2016年10月02日 20:48
  • 6629

三个java超级变态逻辑循环编程题

1:有一根27厘米的细木杆,在第3厘米、7厘米、11厘米、17厘米、23厘米这五个位置上各有一只蚂蚁。木杆很细,不能同时通过一只蚂蚁。开始时,蚂蚁的头朝左还是朝右是任意的,它们只会朝前走或调头,但不会...
  • u011619223
  • u011619223
  • 2015年10月14日 10:31
  • 3300

用9种办法解决 JS 闭包经典面试题之 for 循环取 i

闭包 1.正确的说,应该是指一个闭包域,每当声明了一个函数,它就产生了一个闭包域(可以解释为每个函数都有自己的函数栈),每个闭包域(Function 对象)都有一个 function scope(不...
  • weixin_38409093
  • weixin_38409093
  • 2017年11月22日 15:26
  • 31

用9种办法解决 JS 闭包经典面试题之 for 循环取 i

闭包 正确的说,应该是指一个闭包域,每当声明了一个函数,它就产生了一个闭包域(可以解释为每个函数都有自己的函数栈),每个闭包域(Function 对象)都有一个 function scope...
  • u013243347
  • u013243347
  • 2016年08月06日 10:11
  • 1961

for语句引起一个死循环而引发的思考!!!

对于一个简单地for语句,学过C的朋友可能觉得很简单,但是,看完下面这个看似简单程序还能想明白的朋友(实则并不简单), 那才是真的不错,,好了,不废话了,大家看代码吧!!! #include #i...
  • msdnwolaile
  • msdnwolaile
  • 2016年01月26日 02:27
  • 1550

一个基础的for循环面试题

下面的这段程序主要考察的就是for循环的基础,输出什么??????   public class test { /** * @param args */ public st...
  • lishiyuzuji
  • lishiyuzuji
  • 2011年10月29日 23:53
  • 8181

关于阿里的笔试题for循环中嵌套setTimeout

题目:var a=[1,2,3]; var len=a.length; for(___){ setTimeout{function(){ console.log(__); ...
  • a1247529789
  • a1247529789
  • 2016年04月18日 10:23
  • 2594

从一道面试题(死循环里分配内存)阐述Linux的内存管理

int cnt = 0; while(1) { ++cnt; ptr = (char *)malloc(1024*1024*128); if(ptr == NULL) {...
  • kangquan2008
  • kangquan2008
  • 2014年05月23日 12:59
  • 1102

一道面试题 设计4个线程,其中两个每次对j增加1,另外两个对j每次减少1。循环100次。

题目 设计4个线程,其中两个线程每次对j增加1,另外两个线程对j每次减少1。循环100次。写出程序。 解法1书上的答案是用内部类实现的,网上的答案基本都是照抄书上的。感觉不是很优雅,想自己实现以下...
  • never_cxb
  • never_cxb
  • 2015年12月22日 12:11
  • 2402
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:你真的了解For循环吗?一道For循环Java面试题引发的思考
举报原因:
原因补充:

(最多只允许输入30个字)