NoSuchElementException бесконечный цикл по сравнению с pmd DD-аномалия

#java #while-loop #java.util.scanner #pmd #nosuchelementexception

Вопрос:

Я немного новичок в программировании и очень новичок в gradle и pmd-плагине, так что, пожалуйста, смилуйтесь.

Если пользователь вводит число, scanner.nextLine() будет выдавать исключение NoSuchElementException на каждой итерации, создавая бесконечный цикл.

 public class Console {
    public int readInteger(String line) {
        Integer x = null;
        while(x == null) {
            try(Scanner scanner = new Scanner(System.in) {
                System.out.print(line);
                x = scanner.nextInt();
            } catch(InputMismatchException exc) {
                  //error message
            } catch(InvalidStateException exc) {
                  //error message
            } catch(NoSuchElementException exc) {
                 //error message
            }
        }
        return x;    
    }
}
 

Я буду признателен за каждую руку помощи.

Редактировать: Понял, что моя проблема возникает в сочетании с методом Scanner.nextLine (). Порядок не имеет значения, мой цикл по-прежнему является бесконечным циклом с тем же исключением NoSuchElementException.

Комментарии:

1. Какой ввод вы вводите?

Ответ №1:

Просто измените

 x = scanner.nextLine();
 

Для

 x = scanner.nextInt();
 

Также нет, он не войдет в бесконечный цикл, потому что вы используете неправильный метод, он просто не будет работать .

Комментарии:

1. scanner.nextLine() был ошибкой, не скопировал код, просто запомнил его и записал в вопрос. исправлено, но проблема все еще остается

Ответ №2:

Вот полный (компилируемый) пример:

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

public class Console {
    public int readInteger(String line) {
        Integer x = null;
        while(x == null) {
            try(Scanner scanner = new Scanner(System.in)) {
                System.out.print(line);
                x = scanner.nextInt();
            } catch(InputMismatchException exc) {
                  //error message
            } catch(IllegalStateException exc) {
                  //error message
            } catch(NoSuchElementException exc) {
                 //error message
            }
        }
        return x;
    }

    public static void main(String[] args) {
        Console c = new Console();
        int age = c.readInteger("How old are you? ");
        System.out.printf("You are %d years old.%n", age);
    }
}
 

Примечание: Исключение InvalidStateException не существует, это исключение IllegalStateException.

Сохраните этот фрагмент кода Console.java и запустите его с помощью java 11 , например java Console.java .

Если вы входите, например. 42 это работает. «Бесконечный цикл» начинается, если вы не введете целое число, например very old . Теперь нам нужно на самом деле обработать исключения. В таком случае InputMismatchException будут выброшены. Но неверный ввод не используется и все еще находится в сканере — поэтому повторная попытка с nextInt() вызовет то же исключение снова. Нам придется сначала прочитать неверный токен, прежде чем пользователь сможет ввести новые данные. Мы можем считывать данные с nextLine() помощью , но поэтому нам нужен доступ к сканеру, поэтому нам нужно открыть экземпляр сканера раньше — и выполнить цикл и обработку ошибок внутри внешней попытки с ресурсами.

Если пользователь закроет входной поток (с Ctlr Z под Windows или Cltr D под Linux), то NoSuchElementException будет выброшен, поэтому нам также нужно будет обработать этот случай. IllegalStateException будет выброшено, если сам экземпляр сканера закрыт.

Вот фиксированный полный пример:

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

public class Console {
    public int readInteger(String line) {
        Integer x = null;
        try (Scanner scanner = new Scanner(System.in)) {
            while(x == null) {
                try {
                    System.out.print(line);
                    x = scanner.nextInt();
                } catch(InputMismatchException exc) {
                    String wrongInput = scanner.nextLine();
                    System.out.printf("The input '%s' is not a number. Please try again.%n", wrongInput);
                } catch(NoSuchElementException exc) {
                   // no input provided
                   System.exit(1);
                }
            }
        }
        return x;
    }

    public static void main(String[] args) {
        Console c = new Console();
        int age = c.readInteger("How old are you? ");
        System.out.printf("You are %d years old.%n", age);
    }
}