0

0

Java do-while 循环异常行为解析与输入处理最佳实践

霞舞

霞舞

发布时间:2025-11-03 11:35:49

|

643人浏览过

|

来源于php中文网

原创

Java do-while 循环异常行为解析与输入处理最佳实践

本文深入探讨了java中`do-while`循环在处理用户输入时,因`system.in.read()`方法对输入缓冲区的特殊处理而导致的意外多次执行问题。通过分析回车换行符的影响,文章提出并演示了使用`java.util.scanner`类进行输入处理的解决方案,并提供了清晰的示例代码和最佳实践,旨在帮助开发者避免类似陷阱,编写更健壮的用户交互程序。

在Java编程中,当我们需要从控制台获取用户输入并进行循环验证时,do-while循环是一个常用的结构。然而,如果不正确地处理输入流,可能会遇到循环意外执行多次的问题,尤其是在使用System.in.read()方法时。本教程将深入分析这一现象的根本原因,并提供一个健壮的解决方案。

问题现象:do-while 循环的“多余”执行

考虑以下Java代码片段,它尝试构建一个简单的菜单选择系统:

public class Menu {

    public static void main(String[] args)
    throws java.io.IOException {
        char choice;
        do {
            System.out.println("Help on:");
            System.out.println(" 1. if");
            System.out.println(" 2. while");
            System.out.println(" 3. do-while");
            System.out.println(" 4. for");
            System.out.println(" 5. switch");
            choice = (char) System.in.read(); // 读取用户输入
        } while(choice < '1' || choice > '5'); // 循环条件:当输入不在 '1' 到 '5' 之间时继续循环
    }
}

当用户输入一个无效字符(例如 '6')并按下回车键时,我们期望程序在打印一次菜单后,如果输入无效,则再次打印菜单并等待新的输入。然而,实际运行结果可能如下所示,菜单内容被打印了三次,而不是一次:

Help on:
 1. if
 2. while
 3. do-while
 4. for
 5. switch
6
Help on:
 1. if
 2. while
 3. do-while
 4. for
 5. switch
Help on:
 1. if
 2. while
 3. do-while
 4. for
 5. switch
Help on:
 1. if
 2. while
 3. do-while
 4. for
 5. switch

这种现象表明,在用户输入 '6' 之后,循环体又“额外”执行了两次。

立即学习Java免费学习笔记(深入)”;

根本原因:System.in.read() 与输入缓冲区

造成上述问题的原因在于System.in.read()方法的行为以及操作系统的输入缓冲区。

  1. System.in.read() 的特性:System.in.read()方法从标准输入流中读取一个字节,并将其作为int类型返回。当用户输入一个字符(如 '6')并按下回车键时,实际上发送给程序的是三个字节:

    Teleporthq
    Teleporthq

    一体化AI网站生成器,能够快速设计和部署静态网站

    下载
    • 用户输入的字符本身(例如 '6' 的ASCII码)。
    • 回车符(Carriage Return, \r,ASCII码 13)。
    • 换行符(Line Feed, \n,ASCII码 10)。 这三个字节会依次进入System.in的输入缓冲区。
  2. 循环中的处理:

    • 第一次循环: choice = (char) System.in.read(); 读取了用户输入的 '6'。此时,\r 和 \n 仍然留在输入缓冲区中。
    • 条件判断: choice '5' (即 '6' '5') 为真,因为 '6' > '5'。因此,循环继续。
    • 第二次循环: 再次执行choice = (char) System.in.read();。这次它读取了缓冲区中的 \r。
    • 条件判断: \r 的ASCII码是 13。13
    • 第三次循环: 再次执行choice = (char) System.in.read();。这次它读取了缓冲区中的 \n。
    • 条件判断: \n 的ASCII码是 10。10
    • 第四次循环: 再次执行choice = (char) System.in.read();。此时缓冲区已空,程序会阻塞,等待新的用户输入。

这就是为什么当用户输入一个字符后,do-while循环会“额外”执行两次,因为回车符和换行符也被System.in.read()当作有效的输入并参与了循环条件判断。

解决方案:使用 java.util.Scanner 类

为了避免System.in.read()带来的输入缓冲区问题,推荐使用java.util.Scanner类来处理用户输入。Scanner提供了更高级的方法,如nextInt()、nextLine()等,它们能够更好地解析和消耗输入流中的特定类型数据,并自动处理行终止符。

以下是使用Scanner改进后的代码:

import java.util.InputMismatchException; // 导入InputMismatchException用于处理非整数输入
import java.util.Scanner; // 导入Scanner类

public class MenuImproved {

    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in); // 创建Scanner对象
        int choice; // 使用int类型存储选择

        do {
            System.out.println("Help on:");
            System.out.println(" 1. if");
            System.out.println(" 2. while");
            System.out.println(" 3. do-while");
            System.out.println(" 4. for");
            System.out.println(" 5. switch");

            // 尝试读取整数输入
            try {
                choice = scan.nextInt();
            } catch (InputMismatchException e) {
                System.out.println("无效输入!请输入一个数字。");
                scan.next(); // 消耗掉错误的输入,防止无限循环
                choice = -1; // 设置一个无效值,确保循环继续
            }

        } while (choice < 1 || choice > 5); // 循环条件:当输入不在 1 到 5 之间时继续循环

        System.out.println("您选择了:" + choice); // 打印有效选择
        scan.close(); // 关闭Scanner对象,释放资源
    }
}

代码解析与优势

  1. Scanner scan = new Scanner(System.in);: 创建一个Scanner对象,它包装了System.in输入流。
  2. choice = scan.nextInt();: nextInt()方法会读取并解析输入流中的下一个整数。它会自动跳过任何空白字符(包括回车和换行符),直到找到一个整数。这意味着它会正确地只获取用户输入的数字,而不会将\r和\n作为后续输入。
  3. while (choice 5);: 循环条件保持不变,当用户输入的整数不在 1 到 5 之间时,循环会继续执行,再次提示用户输入。
  4. 异常处理 (try-catch): 增加了try-catch块来捕获InputMismatchException。如果用户输入的不是一个有效的整数(例如输入了字母),nextInt()会抛出此异常。
    • 在catch块中,我们打印错误信息。
    • scan.next();这一行非常重要,它会消耗掉输入流中导致InputMismatchException的非整数令牌。如果没有这一行,Scanner会不断尝试读取相同的无效输入,导致无限循环。
    • choice = -1; 将choice设置为一个明确的无效值,确保在发生异常时循环能够继续。
  5. scan.close();: 在程序结束前,关闭Scanner对象是一个良好的实践,以释放系统资源。

注意事项与最佳实践

  • 混合使用 nextInt() 和 nextLine(): 如果在读取整数(nextInt())、浮点数(nextDouble())或其他非行输入后,紧接着需要读取一整行文本(nextLine()),可能会遇到nextLine()直接读取到之前nextInt()留下的换行符而跳过用户输入的问题。解决方法是在nextInt()之后,手动调用一次scan.nextLine();来消耗掉剩余的换行符。
    int num = scan.nextInt();
    scan.nextLine(); // 消耗掉nextInt()留下的换行符
    String text = scan.nextLine();
  • 输入验证: 始终对用户输入进行验证,以确保其符合程序的预期。Scanner结合try-catch是实现这一目标有效方式。
  • 资源管理: 养成关闭Scanner对象的习惯,特别是在不再需要它时,以避免资源泄露。

总结

do-while循环在用户交互程序中非常有用,但System.in.read()方法在处理控制台输入时,由于其逐字节读取的特性以及对回车换行符的处理方式,容易导致意外的循环行为。通过理解输入缓冲区的机制,并采纳java.util.Scanner类及其提供的高级输入方法(如nextInt()),我们可以更健壮、更安全地处理用户输入,避免不必要的循环执行,从而编写出更可靠的Java应用程序。始终记住对输入进行验证和适当的异常处理,是构建高质量交互式程序的关键。

相关专题

更多
java
java

Java是一个通用术语,用于表示Java软件及其组件,包括“Java运行时环境 (JRE)”、“Java虚拟机 (JVM)”以及“插件”。php中文网还为大家带了Java相关下载资源、相关课程以及相关文章等内容,供大家免费下载使用。

840

2023.06.15

java正则表达式语法
java正则表达式语法

java正则表达式语法是一种模式匹配工具,它非常有用,可以在处理文本和字符串时快速地查找、替换、验证和提取特定的模式和数据。本专题提供java正则表达式语法的相关文章、下载和专题,供大家免费下载体验。

742

2023.07.05

java自学难吗
java自学难吗

Java自学并不难。Java语言相对于其他一些编程语言而言,有着较为简洁和易读的语法,本专题为大家提供java自学难吗相关的文章,大家可以免费体验。

737

2023.07.31

java配置jdk环境变量
java配置jdk环境变量

Java是一种广泛使用的高级编程语言,用于开发各种类型的应用程序。为了能够在计算机上正确运行和编译Java代码,需要正确配置Java Development Kit(JDK)环境变量。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

397

2023.08.01

java保留两位小数
java保留两位小数

Java是一种广泛应用于编程领域的高级编程语言。在Java中,保留两位小数是指在进行数值计算或输出时,限制小数部分只有两位有效数字,并将多余的位数进行四舍五入或截取。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

399

2023.08.02

java基本数据类型
java基本数据类型

java基本数据类型有:1、byte;2、short;3、int;4、long;5、float;6、double;7、char;8、boolean。本专题为大家提供java基本数据类型的相关的文章、下载、课程内容,供大家免费下载体验。

446

2023.08.02

java有什么用
java有什么用

java可以开发应用程序、移动应用、Web应用、企业级应用、嵌入式系统等方面。本专题为大家提供java有什么用的相关的文章、下载、课程内容,供大家免费下载体验。

430

2023.08.02

java在线网站
java在线网站

Java在线网站是指提供Java编程学习、实践和交流平台的网络服务。近年来,随着Java语言在软件开发领域的广泛应用,越来越多的人对Java编程感兴趣,并希望能够通过在线网站来学习和提高自己的Java编程技能。php中文网给大家带来了相关的视频、教程以及文章,欢迎大家前来学习阅读和下载。

16926

2023.08.03

Java JVM 原理与性能调优实战
Java JVM 原理与性能调优实战

本专题系统讲解 Java 虚拟机(JVM)的核心工作原理与性能调优方法,包括 JVM 内存结构、对象创建与回收流程、垃圾回收器(Serial、CMS、G1、ZGC)对比分析、常见内存泄漏与性能瓶颈排查,以及 JVM 参数调优与监控工具(jstat、jmap、jvisualvm)的实战使用。通过真实案例,帮助学习者掌握 Java 应用在生产环境中的性能分析与优化能力。

19

2026.01.20

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Kotlin 教程
Kotlin 教程

共23课时 | 2.7万人学习

C# 教程
C# 教程

共94课时 | 7.1万人学习

Java 教程
Java 教程

共578课时 | 48.4万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号