Java开发笔记(十八)上下求索的while循环
循环是流程控制的又一重要结构,“白天-黑夜-白天-黑夜”属于时间上的循环,古人“年复一年、日复一日”的“日出而作、日落而息”便是每天周而复始的生活。计算机程序处理循环结构时,给定一段每次都要执行的代码块,然后分别指定循环的开始条件和结束条件,就形成了常见的循环语句。最简单的循环结构只需一个while关键字设置循环条件即可,下面是根据输入数字决定循环次数的代码例子:
System.out.println("长夜漫漫,无心睡眠");
System.out.println("请给他设定一个睡醒的年限");
Scanner scan = new Scanner(System.in); // 从控制台接收输入文本
/* nextLine方法表示接收一行文字,以回车键结尾 */
int limit = scan.nextInt();
int year = 0;
while (year < limit) { // 当条件满足时,在循环内部持续处理
System.out.println("已经过去的年份:"+year);
year++;
}
System.out.println("他足足睡了这么多年:"+year);
运行上面的测试代码,输入数字3,连同处理结果的完整日志如下图所示。

单纯的while语句是在每次循环开始前进行条件判断,符合条件则执行一圈代码,不符合的话就退出循环。Java还提供了另一种形式的do-while循环,该循环以do关键字开头,以while语句结尾,并且条件判断也挪到了每次循环结束后再处理了。条件判断的位置变更造成了while循环和do-while循环之间的差异,while循环在开始工作前必定先判断循环条件是否成立,一旦条件不成立,那么当前循环一次都不会执行,直接跳到循环后面的语句了。而do-while循环迟至第一次循环执行完毕才做条件判断,只有发现循环条件不成立时才姗姗来迟退出循环。这意味着,即使循环条件一开始就不满足,do-while循环也一定要进入循环内部,到此一游后才拍拍屁股离开。
下面通过一个实验观察while循环和do-while循环的不同之处,演示代码见下,主要是把循环外围的while改成了do-while:
int year = 0;
do {
System.out.println("已经过去的年份:"+year);
year++;
} while (year < limit); // 当条件满足时,在循环内部持续处理
System.out.println("他足足睡了这么多年:"+year);
然后运行演示代码,倘若输入正数,则while循环和do-while循环打印的日志信息并无区别;要是输入负数,此时二者打印的日志就分道扬镳了。while循环的日志打印结果如下面的左图所示,do-while循环的日志打印结果如下面的右图所示。


从上面的实验结果看出,在条件不满足的情况之下,do-while循环依旧强行遛达了一圈,这种先斩后奏的特性过于武断,故而限制了它的使用范围。
不管是while循环还是do-while循环,它们的条件判断都独立于循环内部代码,要么在循环开始前判断,要么在循环结束后判断。如果要求在内部代码的中间就插入条件判断,并据此决定是退出循环还是继续循环,那又该当若何?为此Java给循环语句引入了break和continue两个关键字,其中break的作用是跳出整个循环,而continue的作用是跳过本次循环的剩余代码、直接继续下次的循环判断和处理。
现在准备修改之前的代码,打算在println和year++中间进行是否继续循环的判断。首先要把while语句后面的条件式子改为true,表示每次循环前后取消默认的条件校验。然后在println和year++之间插入if语句开展条件判断,条件满足的话,就执行year++以及continue操作;条件不满足的话,就直接跳出整个循环,继续循环以外的代码处理。根据上述思路修改循环代码,改好的代码如下所示:
int year = 0;
while (true) { // 当条件满足时,在循环内部持续处理
System.out.println("已经过去的年份:"+year);
if (year < limit) { // 这里判断能否跳出循环
year++;
continue; // 继续下一次循环
} else {
break; // 跳出循环。即跳到while循环的右花括号之后
}
}
System.out.println("他足足睡了这么多年:"+year);
接着运行修改之后的代码,打印出来的循环运行日志如下图所示:

可见此时循环内部接连打印了年份1、年份2、年份3,共三行日志。对比修改之前只打印年份1、年份2的两行日志,显然修改之后的代码逻辑更灵活,因为无论循环的内部代码如何千变万化,程序员总能找到合适的地方退出循环处理。
Java开发笔记(十八)上下求索的while循环的更多相关文章
- Java开发笔记(八十九)缓存字节I/O流
文件输出流FileOutputStream跟FileWriter同样有个毛病,每次调用write方法都会直接写到磁盘,使得频繁的写操作性能极其低下.正如FileWriter搭上了缓存兄弟Buffere ...
- Java开发笔记(八十八)文件字节I/O流
前面介绍了如何使用字符流读写文件,并指出字符流工具的处理局限,进而给出随机文件工具加以改进.随机文件工具除了支持访问文件内部的任意位置,更关键的一点是通过字节数组读写文件数据,采取字节方式比起字符方式 ...
- Java开发笔记(八十六)通过缓冲区读写文件
前面介绍了利用文件写入器和文件读取器来读写文件,因为FileWriter与FileReader读写的数据以字符为单位,所以这种读写文件的方式被称作“字符流I/O”,其中字母I代表输入Input,字母O ...
- Java开发笔记(八十五)通过字符流读写文件
前面介绍了文件的信息获取.管理操作,以及目录下的文件遍历,那么文件内部数据又是怎样读写的呢?这正是本文所要阐述的内容.File工具固然强大,但它并不能直接读写文件,而要借助于其它工具方能开展读写操作. ...
- Java开发笔记(八十四)文件与目录的管理
程序除了处理内存中的数据结构,还要操作磁盘上的各类文件,这里的磁盘是个统称,泛指可以持久保留数据的存储介质,包括但不限于:插在软驱中的软盘.固定在机箱中的硬盘.插在光驱中的光盘.插在USB接口上的U盘 ...
- Java开发笔记(八十二)注解的基本单元——元注解
Java的注解非但是一种标记,还是一种特殊的类型,并且拥有专门的类型定义.前面介绍的五种内置注解,都可以找到对应的类型定义代码,例如查看注解@Override的源码,发现它的代码定义是下面这样的: @ ...
- Java开发笔记(八十)利用反射技术操作私有方法
前面介绍了如何利用反射技术读写私有属性,不单是私有属性,就连私有方法也能通过反射技术来调用.为了演示反射的逆天功能,首先给Chicken鸡类增加下列几个私有方法,简单起见弄来了set***/get** ...
- Java开发笔记(八十七)随机访问文件的读写
前面介绍了字符流读写文件的两种方式,包括文件字符流和缓存字符流,但是它们的写操作都存在一个问题:不管是write方法还是append方法,都只能从文件开头写入,而不能追加到文件末尾或者在文件中间某个位 ...
- Java开发笔记(八十三)利用注解技术检查空指针
注解属于比较高级的Java开发技术,前面介绍的内置注解专用于编译器检查代码,另外一些注解则由各大框架定义与调用,像Web开发常见的Spring框架.Mybatis框架,Android开发常见的Butt ...
- Java开发笔记(八十一)如何使用系统自带的注解
之前介绍继承的时候,提到对于子类而言,父类的普通方法可以重写也可以不重写,但是父类的抽象方法是必须重写的,如果不重写,编译器就直接在子类名称那里显示红叉报错.例如,以前演示抽象类用法之时,曾经把Chi ...
随机推荐
- nginx获取上游真实IP(ngx_http_realip_module)
realip模块的作用是:当本机的nginx处于一个反向代理的后端时获取到真实的用户IP,如果没有realip模块,nginx的access_log里记录的IP会是反向代理服务器的IP,PHP中$_S ...
- python获取函数注释 __doc__
使用 help 函数 可以查看 函数的注释内容 但是它也有点"添油加醋" 其实函数的注释被保存在 __doc__属性里面 PS 双下划线 def f(): "&quo ...
- python语法_列表生成器_生成器_迭代器_异常捕获
列表生成式 a = [x for x in range(10)] print(a) x 可进行操作 a = [x*2 for x in range(10)] print(a) x甚至可以为函数, de ...
- 面试作业之浅析京东促销活动核心模型 - DDD
前言 京东作为中国最大的自营式B2C电商平台,提供一站式综合性购物,服务亿万家庭,涵盖3C.家电.消费品.服饰.家居家装.生鲜和新通路(B2B),满足了消费者的多元化需求.每天都会发布相关的促销活动, ...
- gps 经纬度 转换实际距离
<!doctype html> <html lang="zh-CN"> <head> <meta charset="utf-8& ...
- 【RL-TCPnet网络教程】第18章 BSD Sockets基础知识
第18章 BSD Sockets基础知识 本章节为大家讲解BSD Sockets,需要大家对BSD Sockets有个基础的认识,方便后面章节Socket实战操作. (本章的知识点主要整理自 ...
- Dubbo与Nginx区别
Dubbo的负载均衡已经是服务层面的了,和nginx的负载均衡还在http请求层面完全不同.至于二者哪个优秀,当然没办法直接比较. 涉及到负载均衡就涉及到你的业务,根据业务来选择才是最适合的. dub ...
- 养成这8个编程习惯,你的Python性能将蹭蹭蹭地往上涨
Python不以性能见长,但掌握一些技巧,也可尽量提高程序性能,避免不必要的资源浪费. 1. 使用局部变量 尽量使用局部变量代替全局变量:便于维护,提高性能并节省内存. 使用局部变量替换模块名字空间中 ...
- #Java学习之路——基础阶段(第七篇)
我的学习阶段是跟着CZBK黑马的双源课程,学习目标以及博客是为了审查自己的学习情况,毕竟看一遍,敲一遍,和自己归纳总结一遍有着很大的区别,在此期间我会参杂Java疯狂讲义(第四版)里面的内容. 前言: ...
- 在vue中使用setter改写父子组件传的值
概述 最近在用muse ui的时候碰到一个问题,简单来说是这样的,父子之间传值,父组件和子组件使用相同的props命名,并且子组件不用emit,而用等号赋值. 最后使用计算属性的setter函数解决了 ...