Исключение, возникающее при вызове сканера более одного раза. «Исключение в основном потоке» java.util.NoSuchElementException: строка не найдена»

#java

#java

Вопрос:

Я довольно новичок в Java и только учусь, поэтому, пожалуйста, будьте добры. Я выполняю задачу наследования кода и пытаюсь использовать пользовательские данные для настройки автомобиля перед поездкой.
Когда я вызываю 2 метода, которые я использую для установки параметров со сканером, этот первый метод testCar.drivingTest() работает нормально, однако при testCar.carAgeType() вызове я получаю исключение.

Ниже приведены запросы и входные данные, а также исключение.

Хотели бы вы протестировать подержанный автомобиль сегодня? : y или n

y

отлично, у вас есть водительские права: тип: большие, средние или маленькие

большой

Отлично, вы сдали свой «большой» экзамен. Давайте проверим MOT: type: pass или fail

передать

Какой тип автомобиля вы искали: спортивный, городской или 4X4

 Exception in thread "main" java.util.NoSuchElementException: No line found

at java.base/java.util.Scanner.nextLine(Scanner.java:1651)

at learning.java.Car.carAgeType(Car.java:30)

at learning.java.Main.main(Main.java:17)



Process finished with exit code 1
  

Из того, что я могу собрать при поиске в Google, большинство людей используют .hasNextLine (), чтобы что-то проверить, но я не знаю, что делать или почему это возвращается как false в testCar.carAgeType . оба метода используют в основном один и тот же код, и когда я вызываю только один из методов testCar.carAgeType или testCar.drivingTest, они отлично работают, когда сами по себе, но при вызове один за другим я получаю исключение. Я также не уверен, что делать, когда я использую .hasNextLine, и он возвращает false.

Кто-нибудь может помочь мне понять, почему сканер выдает исключение, когда он вызывается несколькими методами? Любая помощь очень ценится, спасибо.

Приведенный ниже пример кода содержит main и 2 класса: родительский и дочерний классы Vehicle

 import java.util.Scanner;
 
public class Main  {
 
    public static void main(String[] args) {
        Scanner scanner = new Scanner (System.in);
 
        System.out.println("Would you like to test a used car today? : y or n");
 
        if ("y".equals(scanner.nextLine())){
 
            while (true) {
                Car testCar = new Car();
                testCar.drivingTest();
                testCar.carAgeType();
                break;
            }
        }else{
            System.out.println("dang");
        }
        scanner.close();
    }
    
}
 
 
 
 
import java.util.Scanner;
 
public class Vehicle {
    private String licence, MOT;
 
    public Vehicle(){
        this("null", "null");
    }
 
    public Vehicle(String licence, String MOT) {
        this.licence = licence;
        this.MOT = MOT;
    }
 
    public String getLicence() {
        return licence;
    }
 
    public String getMOT() {
        return MOT;
    }
 
 
 
    public void drivingTest(){
        Scanner DTScan = new Scanner (System.in);
        System.out.println("great , do you have a driving licence :type: big, medium or small");
 
            String reply = DTScan.nextLine();
            if ("big".equals(reply) || "medium".equals(reply) || "small".equals(reply)) {
                this.licence = reply;
            } else {
                this.licence = "fail";
            }
            System.out.println("Great you passed your '"   licence   "' exam. Lets check the MOT : type: pass or fail");
            reply = DTScan.nextLine();
            if ("pass".equals(reply) || "fail".equals(reply)) {
                this.MOT = reply;
            } else {
                this.MOT = "invalid";
            }
        DTScan.close();
    }
 
}
 
 
 
 
import java.util.Scanner;
 
public class Car extends Vehicle{
private String type;
private int age;
 
    public Car(){
    }
 
    public Car(String licence, String MOT, String type, int age) {
        super(licence, MOT);
        this.type = type;
        this.age = age;
    }
 
    public String getType() {
        return type;
    }
 
    public int getAge() {
        return age;
    }
 
    public void carAgeType(){
        Scanner ATScan = new Scanner (System.in);
        System.out.println("What type of car were you looking for :type: sports , town or 4X4");
 
          ATScan.nextLine();
          String reply = ATScan.nextLine();
          if ("sports".equals(reply) || "town".equals(reply) || "4X4".equals(reply)) {
              this.type = reply;
          } else {
              this.type = "invalid";
          }
          System.out.println("And what sort of Age :type: between 1 and 10");
          int years = ATScan.nextInt();
          if (years > 0 amp;amp; years < 10) {
              this.age = years;
          } else {
              this.age = -1;
          }
 
        ATScan.close();
 
    }
 
 
}
  

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

1. while (true) { и затем безоговорочно break ? Пожалуйста, удалите его. Это не служит никакой цели.

2. Вы также должны следовать соглашениям об именовании Java: имена переменных и методов записываются в camelCase.

Ответ №1:

 class Main34 {

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        System.out.println("Would you like to test a used car today? : y or n");
        String val = scanner.nextLine();
        if ("y".equals(val)) {

            while (true) {
                Car testCar = new Car();
                testCar.drivingTest(scanner);
                testCar.carAgeType(scanner);
                break;
            }
        } else {
            System.out.println("dang");
        }
        scanner.close();
    }

}


class Vehicle {
    private String licence, MOT;

    public Vehicle() {
        this("null", "null");
    }

    public Vehicle(String licence, String MOT) {
        this.licence = licence;
        this.MOT = MOT;
    }

    public String getLicence() {
        return licence;
    }

    public String getMOT() {
        return MOT;
    }


    public void drivingTest(Scanner scanner) {
        System.out.println("great , do you have a driving licence :type: big, medium or small");

        String reply = scanner.nextLine();
        if ("big".equals(reply) || "medium".equals(reply) || "small".equals(reply)) {
            this.licence = reply;
        } else {
            this.licence = "fail";
        }
        System.out.println("Great you passed your '"   licence   "' exam. Lets check the MOT : type: pass or fail");
        reply = scanner.nextLine();
        if ("pass".equals(reply) || "fail".equals(reply)) {
            this.MOT = reply;
        } else {
            this.MOT = "invalid";
        }
    }
}


class Car extends Vehicle {
    private String type;
    private int age;

    public Car() {
    }

    public Car(String licence, String MOT, String type, int age) {
        super(licence, MOT);
        this.type = type;
        this.age = age;
    }

    public String getType() {
        return type;
    }

    public int getAge() {
        return age;
    }

    public void carAgeType(Scanner scanner) {
        System.out.println("Enter age");
        System.out.println("What type of car were you looking for :type: sports , town or 4X4");
        String reply = scanner.next();
        if ("sports".equals(reply) || "town".equals(reply) || "4X4".equals(reply)) {
            this.type = reply;
        } else {
            this.type = "invalid";
        }
        System.out.println("And what sort of Age :type: between 1 and 10");
        int years = scanner.nextInt();
        if (years > 0 amp;amp; years < 10) {
            this.age = years;
        } else {
            this.age = -1;
        }
    }
}
  

Вместо создания объекта Scanner для каждого вызова вам просто нужно передать существующий объект scanner в метод.

Также вместо прямой проверки if ("y".equals(scanner.nextLine())) вам нужно проверить, используя некоторую переменную, подобную этой if ("y".equals(val))

Попробуйте приведенный выше код, он будет работать нормально.

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

1. Спасибо, я не был уверен, как вызвать / повторно использовать сканер из другого класса. я знал, что будет простой ответ, но я только в начале своего класса.

Ответ №2:

Проблема возникает из-за того, что вы используете Scanner with System.in (который является статическим InputStream ). Всякий раз, когда вы вызываете close() для Scanner , он автоматически закрывает базовый, InputStream в данном случае System.in . После того, как System.in она закрыта, никто другой Scanner не сможет прочитать из нее.

Решение этой проблемы заключается в том, чтобы не закрывать Scanner в каждой из функций, а делать это только в main методе.

Ответ №3:

Из документации Oracle по классу Scanner:

Когда сканер закрыт, он закроет свой источник ввода, если источник реализует закрываемый интерфейс.

Это означает, что когда ваш первый метод закрывает сканер, он закрывает также входные данные (System.in ) и именно поэтому вы получаете исключение, а также почему вызов только одного метода не вызывает исключения.

Просто закройте только первый сканер, который у вас есть в вашем главном, и это должно решить вашу проблему.