while循环和do while循环的区别是什么_

chengsenw 网络营销while循环和do while循环的区别是什么_已关闭评论14阅读模式

记得我刚入行那年,为了一个用户输入验证的功能,在办公室熬到凌晨三点。屏幕上那个该死的循环就像鬼打墙一样,不停地转啊转,我盯着控制台输出的错误日志,恨不得把显示器给砸了。那是我第一次真正理解,为什么导师总说“循环虽简单,用错能要命”。

while循环和do while循环的区别是什么_

今天我想聊聊while和do while这两个看似基础,却让无数程序员栽过跟头的循环结构。话说回来,我可能对while有点偏爱,这大概源于早期被do while坑惨的经历。

先检查再打扫的管家

如果把while循环比作什么,我觉得它像个谨慎的管家——每次打扫房间前,都要先探头看看里面脏不脏。语法上,while就是这样:“先判断条件,再决定执不执行”。

我的团队去年重构过一个数据清洗模块,里面就有个典型的while用例:

while (dataReader.hasNext()) {
    DataRecord record = dataReader.next();
    processRecord(record);
}

这种“先检查后使用”的模式在处理不确定数量的数据时特别安全。有趣的是,我们最初这里用的是do while,结果在空数据集上直接抛了NullPointerException——那可是个线上故障,害得我们半夜被叫起来回滚版本。

话说回来,while循环最让人头疼的就是边界条件。我有个血泪教训:2016年在电商项目做购物车数量校验时,我写了个:

int itemCount = 0;
while (itemCount < maxAllowed) {
    // 处理商品
    itemCount++; 
}

看起来没问题对吧?但测试时发现当maxAllowed为0时,循环居然执行了一次!调试了半天才发现是别处的代码在循环前误改了itemCount。这事教会我:while循环的边界就像走钢丝,稍有不慎就会掉下去。

先递传单再说话的推销员

do while呢?我常开玩笑说它像个热情的推销员——不管你要不要,先把传单塞你手里再说。它的逻辑是“先执行一次,再判断要不要继续”。

坦白说,do while在某些场景下确实很贴心。比如我们做过的命令行工具,要求用户至少输入一次密码:

do {
    System.out.print("请输入密码:");
    password = readInput();
} while (!isValidPassword(password));

这种“保证至少执行一次”的特性,让代码读起来特别自然。我的意思是,既然用户总得输入密码,为什么非要先用while检查呢?

但do while的“热情”有时会过头。2018年我们系统出现过一次内存泄漏,追查下来居然是个do while循环惹的祸:

do {
    byte[] buffer = readChunk();
    process(buffer);
} while (buffer != null);

理论上,当readChunk()返回null时循环应该结束。但实际上,由于网络延迟,第一次读取就可能超时抛出异常,而do while已经分配了内存资源。结果就是在高并发时,这个“至少执行一次”的设计成了资源黑洞。

什么时候该用谁?

凭我这些年的经验,选择循环其实是个权衡题。当你不确定要执行多少次,但很清楚“可能一次都不执行”时,while是更安全的选择。

另一方面,当你确定代码至少需要执行一次,do while往往更直观。比如我们做过的文件解析器:

do {
    FileHeader header = readHeader();
    // 解析文件必须从头开始,不可能跳过header
} while (!header.isValid());

测试数据显示,在同样逻辑下,do while比while平均少了约2ms的判断开销——虽然微不足道,但在高频交易场景下,这种差异会被放大。

等等,我可能说得太绝对了。实际上,现代编译器优化得很厉害,性能差异几乎可以忽略。更重要的考量其实是代码的可读性和维护成本。

那些年我们踩过的坑

我永远记得那个周末晚上,运维打电话说服务器CPU飙到100%。查看日志发现一个while循环在空转:

while (taskQueue.isProcessing()) {
    // 等待任务完成
}

问题出在:某个任务异常后没有更新processing状态,于是这个循环就永远停不下来了。如果当初写成带超时机制的do while,至少还能自动恢复。

还有一次代码审查,我发现新手同事写了这样的代码:

do {
    result = database.query(sql);
    // 处理结果
} while (result.next());

看起来没问题?但在数据库连接异常时,第一次执行就会崩溃。我们最后改成了:

if (database.isConnected()) {
    do {
        result = database.query(sql);
        // 处理结果
    } while (result.next());
}

所以说啊,循环选择不只是技术问题,更是对异常情况的预判。

我的偏见与反思

坦白说,我80%的时间都在用while循环。这种偏好可能源于早期教训——被do while的“无条件执行一次”特性坑过太多次。但平心而论,这确实是我的偏见。

最近在做代码复盘时,我发现团队里do while的使用率只有while的十分之一。这未必是好事,因为有些场景下,do while其实能让代码更简洁。

比如上个月重构的消息队列消费者:

do {
    Message msg = queue.poll();
    if (msg != null) process(msg);
} while (!queue.isEmpty());

比等价的while版本少了重复代码,读起来也顺畅很多。

循环背后的工程哲学

说到底,while和do while的选择反映了一种工程思维:你要多谨慎?愿意为安全性牺牲多少简洁性?

在我的职业生涯中,越来越觉得编程就像生活——没有绝对正确的选择,只有更适合场景的权衡。while教会我审慎,do while让我看到直接行动的价值。

也许有一天,我会改变对do while的保守态度。但至少现在,我还是要说:当你犹豫不决时,选while通常更安全。这不是技术上的最优解,却是工程实践中的稳妥之选。

回头看看这些年写的代码,循环就像老朋友,既帮助我构建了复杂的系统,也用各种bug让我成长。下次写循环时,不妨多想三秒钟:这个循环真的需要执行吗?如果必须执行,它最少应该执行几次?

相信我,这点思考能帮你避开很多深夜调试的煎熬。毕竟,凌晨三点的办公室咖啡,真的不好喝。

 
chengsenw
  • 本文由 chengsenw 发表于 2025年12月5日 07:17:56
  • 转载请务必保留本文链接:https://www.gewo168.com/6219.html