为什么我会收到 NoSuchElementException?

Why am I receiveing a NoSuchElementException?

当我 运行 我的程序时,我在我的 Eclipse 控制台中得到这个:

Type a number then press enter.
1. Add a customer
2. Add an order
3. Remove an order
4. Ship an order
5. Print pending orders with customer information
6. Restock parts
7. Exit
1
Loading driver...
Driver loaded!
Connecting database...
Database connected!
Enter 5 letters or less to identify the customer as.
Exception in thread "main" java.util.NoSuchElementException: No line found
    at java.util.Scanner.nextLine(Scanner.java:1540)

我试过只使用一个扫描仪而不关闭它,但没有用。有人可以帮我弄清楚为什么我会在 tempCustID = keyboard1.nextLine(); 行收到这条消息吗?奇怪的是,在读取 int seed = keyboard.nextInt();.

的前一行中没有发生错误

这是我的 Menu.java class 的代码:

import java.sql.Connection;
import java.sql.SQLException;

public class Menu {

    public static void main(String[] args) throws SQLException {
        // TODO Auto-generated method stub

        DatabaseModifier session = new DatabaseModifier();
        int seed = session.options();
        Connection mycon = session.connectDB();

        while(seed != 7) {
            if(seed == 1) {
                session.addCust(mycon);
            }else if(seed == 2) {
                //session.addOrder(mycon);
            }else if(seed == 3) {

            }else if(seed == 4) {

            }else if(seed == 5) {

            }else if(seed == 6) {

            }else {
                System.out.println("Invalid option.");
            }
            seed = session.options();
        }
        System.out.println("Good-bye.");
    }
}

这是我的 DatabaseModifier.java class 的代码:

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Scanner;

public class DatabaseModifier {

    public int options() {      
        System.out.println("Type a number then press enter.");
        System.out.println("1. Add a customer");
        System.out.println("2. Add an order");
        System.out.println("3. Remove an order");
        System.out.println("4. Ship an order");
        System.out.println("5. Print pending orders with customer information");
        System.out.println("6. Restock parts");
        System.out.println("7. Exit");

        Scanner keyboard = new Scanner(System.in);
        int seed = keyboard.nextInt();
        keyboard.close();

        return seed;
    }

    public Connection connectDB() {
        String url = "jdbc:mysql://localhost:3306/northwind?useSSL=false&serverTimezone=EST";
        String username = "root";
        String password = "password";

        System.out.println("Loading driver...");

        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            System.out.println("Driver loaded!");
        }catch (ClassNotFoundException e) {
            throw new IllegalStateException("Cannot find the driver in the classpath!", e);
        }

        System.out.println("Connecting database...");

        try {
            Connection mycon = DriverManager.getConnection(url, username, password);
            System.out.println("Database connected!");
            return mycon;
        } catch (SQLException e) {
            throw new IllegalStateException("Cannot connect the database!", e);
        }
    }

    public void addCust(Connection mycon) throws SQLException {
        String tempCustID, custID, comp, contName, contTitle, addr, city, reg, postCode, country, phone, fax;

        Scanner keyboard1 = new Scanner(System.in);

        int correctInput = 0;
        do {
            PreparedStatement stat = mycon.prepareStatement("SELECT CustomerID FROM customers");
            ResultSet cust = stat.executeQuery();
            System.out.println("Enter 5 letters or less to identify the customer as.");
            tempCustID = keyboard1.nextLine();
            custID = tempCustID.toUpperCase();
            while (cust.next()) {
                String customerID = cust.getString("CustomerID");
                if (custID.equals(customerID) || "".equals(custID) || "NULL".equals(custID) || "null".equals(custID) || custID.length() > 5) {
                    System.out.println(
                            "Customer ID already exists or you entered incorrect input. Please enter a different sequence of 5 letters or less to identify the customer as.");
                }else
                    correctInput = 1;
            }
        }while(correctInput == 0);

        correctInput = 0;
        do {
            PreparedStatement stat1 = mycon.prepareStatement("SELECT CompanyName FROM customers");
            ResultSet comp1 = stat1.executeQuery();
            System.out.println("Enter 40 letters or less to identify the company name.");
            comp = keyboard1.nextLine();
            while (comp1.next()) {
                String compName = comp1.getString("CompanyName");
                if (compName.equals(comp) || "".equals(comp) || "NULL".equals(comp) || "null".equals(comp) || comp.length() > 40) {
                    System.out.println(
                            "Company name already exists or you entered incorrect input. Please enter a different sequence of 40 letters or less to identify the company as.");
                }else
                    correctInput = 1;
            }
        }while(correctInput == 0);

        correctInput = 0;
        do {
            System.out.println("Enter 30 letters or less to identify the contact's first and last name.");
            contName = keyboard1.nextLine();
            if ("".equals(contName) || "NULL".equals(contName) || "null".equals(contName) || contName.length() > 30) {
                System.out.println("Incorrect input.");
            }else
                correctInput = 1;
        }while(correctInput == 0);


        correctInput = 0;
        do {
            System.out.println("Enter 30 letters or less to identify the contact's job title.");
            contTitle = keyboard1.nextLine();
            if ("".equals(contTitle) || "NULL".equals(contTitle) || "null".equals(contTitle) || contTitle.length() > 30) {
                System.out.println("Incorrect input.");
            }else
                correctInput = 1;
        }while(correctInput == 0);


        correctInput = 0;
        do {
            System.out.println("Enter 60 letters or less to identify the company's address.");
            addr = keyboard1.nextLine();
            if ("".equals(addr) || "NULL".equals(addr) || "null".equals(addr) || addr.length() > 60) {
                System.out.println("Incorrect input.");
            }else
                correctInput = 1;
        }while(correctInput == 0);

        correctInput = 0;
        do {
            System.out.println("Enter 15 letters or less to identify the company's city.");
            city = keyboard1.nextLine();
            if ("".equals(city) || "NULL".equals(city) || "null".equals(city) || city.length() > 15) {
                System.out.println("Incorrect input.");
            }else
                correctInput = 1;
        }while(correctInput == 0);

        correctInput = 0;
        do {
            System.out.println("Enter 15 letters or less to identify the company's region.");
            reg = keyboard1.nextLine();
            if ("".equals(reg) || "NULL".equals(reg) || "null".equals(reg) || reg.length() > 15) {
                System.out.println("Incorrect input.");
            }else
                correctInput = 1;
        }while(correctInput == 0);

        correctInput = 0;
        do {
            System.out.println("Enter 10 letters or less to identify the company's postal code.");
            postCode = keyboard1.nextLine();
            if ("".equals(postCode) || "NULL".equals(postCode) || "null".equals(postCode) || postCode.length() > 10) {
                System.out.println("Incorrect input.");
            }else
                correctInput = 1;
        }while(correctInput == 0);

        correctInput = 0;
        do {
            System.out.println("Enter 15 letters or less to identify the company's country.");
            country = keyboard1.nextLine();
            if ("".equals(country) || "NULL".equals(country) || "null".equals(country) || country.length() > 15) {
                System.out.println("Incorrect input.");
            }else
                correctInput = 1;
        }while(correctInput == 0);

        correctInput = 0;
        do {
            System.out.println("Enter 24 letters or less to identify the company's phone number.");
            phone = keyboard1.nextLine();
            if ("".equals(phone) || "NULL".equals(phone) || "null".equals(phone) || phone.length() > 24) {
                System.out.println("Incorrect input.");
            }else
                correctInput = 1;
        }while(correctInput == 0);

        correctInput = 0;
        do {
            System.out.println("Enter 24 letters or less to identify the company's fax.");
            fax = keyboard1.nextLine();
            if ("".equals(fax) || "NULL".equals(fax) || "null".equals(fax) || fax.length() > 24) {
                System.out.println("Incorrect input.");
            }else
                correctInput = 1;
        }while(correctInput == 0);

        keyboard1.close();

        PreparedStatement newCust = mycon.prepareStatement(
                "INSERT INTO customers" + "(CustomerID, CompanyName, ContactName, ContactTitle, Address, "
                        + "City, Region, PostalCode, Country, Phone, Fax)" + "VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
        newCust.setString(1, custID);
        newCust.setString(2, comp);
        newCust.setString(3, contName);
        newCust.setString(4, contTitle);
        newCust.setString(5, addr);
        newCust.setString(6, city);
        newCust.setString(7, reg);
        newCust.setString(8, postCode);
        newCust.setString(9, country);
        newCust.setString(10, phone);
        newCust.setString(11, fax);
        newCust.executeUpdate();
    }

扩展并澄清 user3170251 的评论,关闭 Scanner 也会关闭基础数据源,如果该源实际上是 Closeable:

If this scanner has not yet been closed then if its underlying readable also implements the Closeable interface then the readable's close method will be invoked. If this scanner is already closed then invoking this method will have no effect.

(Scanner.close() javadocs)

作为 InputStream,您的输入源 System.in 确实是 Closeable。一旦关闭,它就关闭了——无法从中进一步读取任何内容,即使您将它包装在一个新的 Scanner 中也是如此。这就是为什么你第二次和随后的 DataBaseModifier.options() 调用抛出。

解决方法是避免关闭System.in。此外,最安全的做法是重复使用单个 Scanner 而不是创建一个新的,因为数据可能会缓冲在 Scanner 中并在您关闭它时丢失。有几种方法可以解决该问题,但一个非常简单的方法是使 Scanner 成为实例变量而不是局部变量。在实例化 class 时对其进行初始化,并使其永远打开。