Java Magazine上面有一个专门坑人的面试题系列: https://blogs.oracle.com/javamagazine/quiz-2。

这些问题的设计宗旨,主要是测试面试者对Java语言的了解程度,而不是为了用弯弯绕绕的手段把面试者搞蒙。

如果你看过往期的问题,就会发现每一个都不简单。

这些试题模拟了认证考试中的一些难题。 而 “中级(intermediate)” 和 “高级(advanced)” 指的是试题难度,而不是说这些知识本身很深。 一般来说,“高级”问题会稍微难一点。

请回答一个问题: 在使用循环进行遍历时,你更喜欢使用哪种循环: for 还是 while

问题(中级难度)

问题的目标是比较Java中各种循环的语法。

假设需要编写程序,在控制台引导用户输入,并进行响应, 执行的步骤大致是这样的:

  1. 输出提示和引导信息;
  2. 读取用户输入的指令;
  3. 如果指令为 quit, 则退出程序;如果输入其他指令,则执行对应的逻辑,完成后跳转到第1步。

要实现上述功能,使用哪种语法和方式最好? 请选择:

  • A、 使用 for 循环和 break 语句;
  • B、 使用简写/增强的 for 循环;
  • C、 使用 while 循环和 continue 语句;
  • D、 使用 do/while 循环;

答案和解析

这个问题要求做一个最佳选择,一般不会让你选择多个答案。

有两个关键的地方,可以帮助我们进行判断。
一、 步骤1和步骤2都必须至少执行一次; 也就是说,至少要读取一个命令之后,代码才会退出。
二、 在读取命令之前,不可能做出退出程序的决定。

让我们考虑一下,如果使用 【while循环】需要怎么处理。
首先 while 循环在入口处执行条件判断; 该测试是在循环体执行之前执行的。
所以,如果使用while 循环来进行控制,一种可能的方式,是在循环开始之前打印提示并读取命令,伪代码所下所示:

Issue prompt                  // 打印提示引导信息
Read command                  // 读取用户指令
While (command is not "quit") // 判断如果命令不是quit才进入循环Execute the command         // 执行命令......

可能初看起来没有什么问题,但我们还需要提示并并读取后续命令。
每次的循环操作中都需要执行这个操作的相关代码。
也就是说会有代码重复。伪代码示例如下:

Issue prompt                  // 打印提示引导信息
Read command                  // 读取用户指令
While (command is not "quit") // 判断如果命令不是quit才进入循环Execute the command         // 执行命令Issue prompt                // 打印提示引导信息; 【重复代码】Read command                // 读取用户指令; 【重复代码】
End-while                     // while循环结束

重复代码不仅看起来不爽,在维护过程中也容易出错,对于追求卓越的程序员来说是不好的习惯。
另一种方式,是在循环之前将命令设置为某个虚拟值,并确保在碰到虚拟命令时不会执行任何操作。
这能避免重复代码,但也会带来额外的复杂性,以后阅读代码的人可能难以理解,因为必须使用特殊的值来进行“hack”。

这种情景直接使用 while 循环肯定不太合理,下面我们再来看看其他方案。

接下来,看看如果使用 【for循环】 怎么处理。
for 循环实际上是另一种方式的 while 循环, 目的是为了在某些场景下编程更加直观和容易理解。
常见的两种场景是:

  • 一、 将循环中使用的一些变量进行声明和初始化。
  • 二、 在迭代过程中更新某些变化量。

从根本上来说, forwhile 循环加一些额外部分形成的。
在这个场景中,这些额外部分可能会有用,但仍然会存在重复的 [提示和读取输入] 代码。

然后我们一起来考察【简写的for循环】(enhanced for loop,增强的for循环)。
增强的for循环提供了一种简洁的方式来遍历可迭代对象(Iterable object,如集合/数组)。
在本文指定的问题中,必须从控制台读取输入命令,当输入值为 quit 时循环终止。
虽然也可以创建一个 Iterable 对象来引导提示用户,并读取文本内容,如果输入不是quit时就返回字符串。 如果用户的输入是 quit,则终止迭代,但对于这个场景来说,这种实现方式就很复杂了,而且也不直观。
在这种情况下,似乎不能推荐使用增强的for循环,可以把它留下作为备选,看看有没有更好的方式。

剩下的选项是 do/while 循环。 这种方式将决定是否继续循环的测试条件放在 do/while 结构的末尾,
效果就是 do/while 循环的body至少会被执行一次,因为必须先执行body之后才能到达测试条件判断。
也就是循环体是在判断条件之前执行的。
do/while 主要就是适用于这样的场景: 可以在循环体中进行引导提示,并读取命令输入。
这样就没有重复的代码,确保提示和输入发生在条件判断之前,代码结构会比较干净和简洁。

那么很明显, 选项D非常适合这个场景, 因此,它是比其他选项更好的选择。

通过这些解析,我们最终可以说 选项D是正确答案,而选项A、B和C是不正确的。

注: 选项A中提到使用 break 语句,而选项C提到使用 continue 语句。
虽然使用 forbreak的方式也可以让循环体强制执行,但这两种方式的代码也不会很优雅。

选项A的伪代码大致如下:

for (;;) {                   // 死循环......                   // 展示引导和提示信息String input = ...       // 读取用户输入if (input.equals("quit"))break;               // 如果是quit则退出循环executeCommand(input);   // 否则就执行命令...
}

但依然没有 do/while 方式直观和简洁。

而在 while 循环中使用 continue 则是标准的错误答案,你没法构造出一个可执行的解决方案。

总结

正确的选项是D。

do/while 主要就适用这种至少执行1次的场景。

当然,在某些开源代码中你会发现只执行一次的代码使用了 do{ if-break; } while(true); 的方式,这种方式的好处是可以减少if嵌套的深度,必要时进行中断。 一层一层的嵌套代码实际上是难以维护和理解的,而抽象为方法又涉及传值的问题,所以怎么方便就怎么来是比较好的选择。

相关链接

  • Java坑人面试题系列: 包装类(中级难度)
  • Java坑人面试题系列: 比对while与for循环(中级)
  • Java坑人面试题系列: 集合(高级)
  • Java坑人面试题系列: 线程/线程池(高级)
  • Java坑人面试题系列: 变量声明(中级)

原文链接: https://blogs.oracle.com/javamagazine/quiz-intermediate-loop-constructs

Java坑人面试题系列: 比对while与for循环(中级难度)相关推荐

  1. Java坑人面试题系列: 线程/线程池(高级难度)

    ExecutorService 接口及相关API细节详解. Java Magazine上面有一个专门坑人的面试题系列: https://blogs.oracle.com/javamagazine/qu ...

  2. 【Java实习生面试题系列】-- 多线程篇四

    文章目录 1. 说下对同步器 AQS 的理解? 2. AQS 的原理是什么? 3. AQS 底层使用了模板方法模式,你能说出几个需要重写的方法吗? 4. 说下对 Semaphore.CountDown ...

  3. 【Java实习生面试题系列】-- JVM篇一

    文章目录 1. 说一下 JVM 的主要组成部分?及其作用? 2. 堆和栈的区别是什么? 3. 对象的访问定位的两种方式? 4. 判断垃圾可以回收的方法有哪些? 5. 被标记为垃圾的对象一定会被回收吗? ...

  4. Java基础面试题系列

    本文收集了一些经典的Java面试题 1.面向对象的特征有哪些方面? 答:面向对象的特征主要有以下几个方面: 抽象:抽象是将一类对象的共同特征总结出来构造类的过程,包括数据抽象和行为抽象两方面.抽象只关 ...

  5. 【Java实习生面试题系列】-- 多线程篇一

    文章目录 1. 并行和并发有什么区别? 2. 线程和进程的区别? 3. 守护线程是什么? 4. 创建线程的几种方式? 5. Runnable 和 Callable 有什么区别? 6. 线程状态及转换? ...

  6. 一文整理总结常见Java后端面试题系列——Java虚拟机篇(2022最新版)

    关于作者

  7. 一文整理总结常见Java后端面试题系列——设计模式篇(2022最新版)

    关于作者

  8. Java算法面试题(007) 蒙提霍尔问题(三门问题)

    简介 此问题本身和算法无关,本质上一个关于概率的问题,在一些高等级的面试也经常被问及,因此收录在Java算法面试题系列中. 三门问题(Monty Hall problem)亦称为蒙提霍尔问题.蒙特霍问 ...

  9. JAVA线程面试题书目录

    JAVA线程面试题之1) 什么是线程? JAVA线程面试题之2) 线程和进程有什么区别? JAVA线程面试题之3) 如何在Java中实现线程? JAVA线程面试题之4) 用Runnable还是Thre ...

最新文章

  1. 有空时深入阅读这两篇文章
  2. Chocolates
  3. 揭秘IT人才特点:中美印日四国程序员比较
  4. hibernate annotation注解方式来处理映射关系
  5. 怎么写显示商品图片_虾皮商店封面图片 虾皮商店介绍怎么写吸引人
  6. PHP设计模式——备忘录模式
  7. 关于 it行业未来 的个人判断
  8. 分享MYSQL中的各种高可用技术
  9. HTTP协议学习总结三(常见http响应头)
  10. python怎么修改界面颜色_python中颜色设置
  11. 2016年计算机考研大纲,2016考研计算机大纲解析
  12. oracle清理磁盘空间
  13. 月入万元的自由程序员 (转电脑报)
  14. (3)数仓建设-数据仓库设计方案
  15. vscode背景图片无法删除
  16. 关于导数非常的好文章
  17. 模型稳定度指标PSI
  18. 1.Java集合框架是什么?说出一些集合框架的优点?
  19. DirBuster的初涉使用笔记
  20. linux 用dg分区,dg的奇怪问题终结和分区问题答疑

热门文章

  1. 勃林格殷格翰2022年营收强势增长10.5%,达241亿欧元
  2. 神通数据库安装及使用手册
  3. “喜报云报销”荣获中国金软件移动互联网领域最具应用价值解决方案奖
  4. 1月份国产手机出货量大幅下滑,iPhone却逆势增100万
  5. 2019.03.26 bzoj4444: [Scoi2015]国旗计划(线段树+倍增)
  6. 数学与计算机科学虎扑,数学发展到今天还有继续研究的必要吗?
  7. 谷粒商城项目篇8_分布式高级篇_商城首页、性能压测、优化(Nginx动静分离)
  8. 独立对honor荣耀来说有哪些好处?
  9. Canvas笔触调整-8
  10. Devops之制品库平台nexus实践