【问题标题】:Program is looping forever in Java [duplicate]程序在 Java 中永远循环 [重复]
【发布时间】:2022-12-07 00:03:30
【问题描述】:

该程序非常简单。你输入你的出生年份,它会打印出你的年龄。但是,当用户输入字符而不是数值时,我试图处理异常。但随后程序开始永远循环。

import java.util.InputMismatchException;
import java.util.Scanner;

public class Main {

    public static void main(String[] args) {

        Scanner scanner = new Scanner(System.in);

        System.out.println("Current year is 2022, enter your date of birth: ");
        boolean isValid = false;
        int age=0;
        int dateOfBirth;
        do {
            try {
                dateOfBirth = scanner.nextInt();
                scanner.nextLine();
                age = 2022 - dateOfBirth;
                isValid = age < 0 ? false : age > 125 ? false : true;
            }
            catch (InputMismatchException e) {
                System.out.println("Error");
            }
            if(!isValid) {
                System.out.println("Date of birth is not valid please try again");
            }
        } while (!isValid);
        System.out.println("You are "+age+" years old");
    }
}

【问题讨论】:

  • 这是练习一些基本调试的好机会。您可以学习使用调试器,但您也可以只添加 printlns 以查看您的 try 块到底有多远,以及它分配给 dateOfBirthageisValid 的值。这将准确地向您展示哪些逻辑未按您预期的方式运行。
  • 我无权访问 JVM 或编译器,因此我无法对此进行测试,但它可能是 dateOfBirth = scanner.nextInt() 行。它在 age = 2022 - dateOfBirth 时被调用,然后在 isValid = age < 0 时被调用?错误:年龄 > 125?错误:正确。

标签: java loops exception


【解决方案1】:

Scanner 将字符流转换为标记流。每个 next() 调用(但不包括 nextLine,这很奇怪,您可能永远不应该调用它)都会消耗一个令牌。或者,如果不能,它不会,这就是问题所在。

首先,让我们修理扫描仪。完成后,scanner.useDelimiter("\R"); 告诉它 enter 按下单独的标记(这是你已经期望的),现在停止调用 nextLine。这解决了一些问题。

然后,当您调用 .nextInt() 时,会发生以下情况:

  • 如果下一个标记可以解析为一个 int,它作为一个 int 被使用和返回。
  • 如果不是,就是不是消费,并抛出InputMismatchException

因此,此代码将永远循环:假设未使用令牌,则仍然有一个令牌(无法转换为 int),以便下一个循环立即失败。因此,解决方案是:使用 s.next(); 简单地使用无效令牌(next() 不能以这种方式“失败”,并使用下一个令牌,无论它是什么)。将 scanner.next(); 放入您的 catch (InputMismatchException e) 块中。

【讨论】:

  • 也可以将 scanner.nextLine(); 移动到 if(!isValid) 中,这也很有魅力
  • 如果用户使用键盘上最大的键,那将会中断。一般来说,“调用.nextX(),然后总是调用.nextLine()”的模型是愚蠢的。很遗憾非常在 SO 和其他地方广泛存在。修复是.useDelimiter("\R"),你应该这样做全部旨在读取键盘输入的扫描仪。
  • 尝试输入和空间,它并没有真正打破。它只是仍在等待正确的输入
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-04-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-20
  • 2016-04-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多