Java 验证有问题:即使逻辑看起来很好,也会出现无限循环

Java 验证有问题:即使逻辑看起来很好,也会出现无限循环,java,while-loop,java.util.scanner,Java,While Loop,Java.util.scanner,我正在做这个“餐厅”项目,它需要两个输入:账单金额和1到3的满意度水平。我尝试使用hasNextDouble()验证每个输出,但由于某种原因,当我运行程序时,第一个if语句中的else语句无限运行。谁能看看这个吗 package tips; import java.util.Scanner; public class Tips { public static void main(String[] args) { /* Ask for the diners’ satisfaction

我正在做这个“餐厅”项目,它需要两个输入:账单金额和1到3的满意度水平。我尝试使用hasNextDouble()验证每个输出,但由于某种原因,当我运行程序时,第一个if语句中的else语句无限运行。谁能看看这个吗

package tips;

import java.util.Scanner;

public class Tips {

public static void main(String[] args) {
    /* Ask for the diners’ satisfaction level using these ratings: 
    1 = Totally satisfied, 2 = Satisfied, 3 = Dissatisfied.
    If the diner is totally satisfied, calculate a 20 percent tip.
    If the diner is satisfied, calculate a 15 percent tip.
    If the diner is dissatisfied, calculate a 10 percent tip.
    Report the satisfaction level and tip in dollars and cents.*/

    Scanner in = new Scanner(System.in);

    boolean isDouble = false;
    boolean isInt = false;

    TipsCalculator tips = new TipsCalculator();

    while (!isDouble && !isInt) {
          System.out.print("Please enter the bill amount: ");
          //Checks if the input is a double.
          if(in.hasNextDouble()) {
              tips.setBill(in.nextDouble());
              isDouble = true;
          } else {
              System.out.println("The value entered is not a valid amount.");
              continue;
          }

          System.out.println("Please enter your satisfaction level: \n1 = Totally Satisfied.\n2 = Satisfied.\n3 = Dissatisfied.");
          //Checks if the input is an integer.
          if(in.hasNextInt()) {
              tips.setSatisfactionLevel(in.nextInt());
              isInt = true;
              //Prints different outputs depending on the satisfaction level.
              if (tips.getSatisfactionLevel() == 1) {
                  System.out.println("You are totally satisfied! :-)" + 
                          ". \n" + 
                          "Your tip amount is: " + 
                          tips.calculateTips());
              } else if (tips.getSatisfactionLevel() == 2){
                  System.out.println("You are satisfied! :-)" + 
                          ". \n" + 
                          "Your tip amount is: " + 
                          tips.calculateTips());
              } else if (tips.getSatisfactionLevel() == 3) {
                  System.out.println("You are dissatisfied! :-(" + 
                          ". \n" + 
                          "Your tip amount is: " + 
                          tips.calculateTips());
              } else {
                  //Error if the level is not from 1 to 3.
                  System.out.println("The value entered is not between 1 and 3");
              }
          } else {
              System.out.println("The value entered is not between 1 and 3");
              continue;
          }
    } in.close();

}

}

isDoubl
isInt
都是假的,所以
!是双重的&!isInt
将始终为真。这是无限循环背后的根本原因。不要将输入读取为double和int。将其读取为字符串,然后在代码中将其解析为double或Integer。在Integer和Double类中使用方法valueOf(String)。要分析字符串,无限循环的原因是: Scanner中的hasNextDouble方法类内部调用hasNext方法。 它是这样写的

public boolean hasNext(Pattern pattern) {
        ensureOpen();
        if (pattern == null)
            throw new NullPointerException();
        hasNextPattern = null;
        saveState();

        while (true) {
            if (getCompleteTokenInBuffer(pattern) != null) {
                matchValid = true;
                cacheResult();
                return revertState(true);
            }
            if (needInput)
                readInput();
            else
                return revertState(false);
        }
    }
在上面的方法中,getCompleteTokeinBuffer方法调用才是真正的罪魁祸首。此getCompleteTokenInBuffer可以返回以下3种可能性

/*
 * 1. valid string means it was found
 * 2. null with needInput=false means we won't ever find it
 * 3. null with needInput=true means try again after readInput
 */
hasNextmthod中,每当我们第一次输入非双精度值时,我们将能够读取数据,getCompleteTokeinBuffer将返回null,并将第一次设置needInput=false。但是,第二次,hasNext方法将返回值false,因为needInput=false条件将为true


needInput=false条件将在随后的hasNextDouble方法调用中保持为true。由于这个原因,我们无法读取任何数据,这导致了无限循环。

噢,当我输入一个十进制数字时会出现错误,如:39.4如果您不在美国,您可能需要在.useLocale(locale.US)中设置区域设置;如果我输入39,它工作正常……那没有意义-!操作员不是这样吗!如果isDouble设置为false,则isDouble为true。允许用户自己为您提供输入、解析和验证是一种更好的做法。因此,您将输入作为原始数据读取,然后才对其进行验证。