Я новичок в использовании Java, но у меня есть некоторый предыдущий опыт работы с C #. Проблема, с которой я сталкиваюсь, связана с чтением пользовательского ввода с консоли.
Я сталкиваюсь с ошибкой "java.util.NoSuchElementException" в этой части кода:
payment = sc.next(); // PromptCustomerPayment function
У меня есть две функции, которые получают пользовательский ввод:
PromptCustomerQty
PromptCustomerPayment
Если я не вызываю PromptCustomerQty, я не получаю эту ошибку, что наводит меня на мысль, что я делаю что-то не так со сканером. Ниже приведен мой полный пример кода. Я ценю любую помощь.
publicstaticvoidmain(String[] args) {
// Create a customer // Future proofing the possabiltiies of multiple customers Customercustomer=newCustomer("Will");
// Create object for each Product // (Name,Code,Description,Price) // Initalize Qty at 0 ProductComputer=newProduct("Computer","PC1003","Basic Computer",399.99); ProductMonitor=newProduct("Monitor","MN1003","LCD Monitor",99.99); ProductPrinter=newProduct("Printer","PR1003x","Inkjet Printer",54.23);
// Define internal variables // ## DONT CHANGE ArrayList<Product> ProductList = newArrayList<Product>(); // List to store Products StringformatString="%-15s %-10s %-20s %-10s %-10s %n"; // Default format for output
// Add objects to list ProductList.add(Computer); ProductList.add(Monitor); ProductList.add(Printer);
// Ask users for quantities PromptCustomerQty(customer, ProductList);
// Ask user for payment method PromptCustomerPayment(customer);
// Create the header PrintHeader(customer, formatString);
// Create Body PrintBody(ProductList, formatString); }
publicstaticvoidPromptCustomerQty(Customer customer, ArrayList<Product> ProductList) { // Initiate a Scanner Scannerscan=newScanner(System.in);
// Prompt User do { System.out.println("Would you like to pay in full? [Yes/No]"); System.out.print("> ");
payment = sc.next();
} while ((!payment.toLowerCase().equals("yes")) && (!payment.toLowerCase().equals("no")));
// Check/set result if (payment.toLowerCase().equals("yes")) { customer.setPaidInFull(true); } else { customer.setPaidInFull(false); }
// Cleanup sc.close(); }
Переведено автоматически
Ответ 1
Это действительно озадачивало меня некоторое время, но это то, что я нашел в конце.
При вызове sc.close() первого метода он не только закрывает ваш сканер, но и закрывает ваш System.in поток ввода. Вы можете проверить это, напечатав его состояние в самом верху второго метода как :
System.out.println(System.in.available());
Итак, теперь, когда вы повторно создаете экземпляр, Scanner во втором методе он не находит никакого открытого System.in потока и, следовательно, исключения.
Я сомневаюсь, что есть какой-либо выход для повторного открытия System.in потому что:
public void close() throws IOException --> Closes this input stream and releases any system resources associated with this stream. The general contract of close is that it closes the input stream. A closed stream cannot perform input operations and **cannot be reopened.**
Единственное хорошее решение вашей проблемы - инициировать Scanner в вашем основном методе, передать это в качестве аргумента в ваших двух методах и снова закрыть его в вашем основном методе, например:
main блок кода, связанный с методом:
Scannerscanner=newScanner(System.in);
// Ask users for quantities PromptCustomerQty(customer, ProductList, scanner );
// Ask user for payment method PromptCustomerPayment(customer, scanner );
Таким образом, scan.close() закрывается System.in.
Чтобы исправить это, вы можете сделать
Scanner scanstatic и не закрывайте его в PromptCustomerQty . Приведенный ниже код работает.
publicstaticvoidmain(String[] args) {
// Create a customer // Future proofing the possabiltiies of multiple customers Customercustomer=newCustomer("Will");
// Create object for each Product // (Name,Code,Description,Price) // Initalize Qty at 0 ProductComputer=newProduct("Computer","PC1003","Basic Computer",399.99); ProductMonitor=newProduct("Monitor","MN1003","LCD Monitor",99.99); ProductPrinter=newProduct("Printer","PR1003x","Inkjet Printer",54.23);
// Define internal variables // ## DONT CHANGE ArrayList<Product> ProductList = newArrayList<Product>(); // List to store Products StringformatString="%-15s %-10s %-20s %-10s %-10s %n"; // Default format for output
// Add objects to list ProductList.add(Computer); ProductList.add(Monitor); ProductList.add(Printer);
// Ask users for quantities PromptCustomerQty(customer, ProductList);
// Ask user for payment method PromptCustomerPayment(customer);
// Create the header PrintHeader(customer, formatString);
// Create Body PrintBody(ProductList, formatString); }
// Prompt User do { System.out.println("Would you like to pay in full? [Yes/No]"); System.out.print("> ");
payment = scan.next();
} while ((!payment.toLowerCase().equals("yes")) && (!payment.toLowerCase().equals("no")));
// Check/set result if (payment.toLowerCase() == "yes") { customer.setPaidInFull(true); } else { customer.setPaidInFull(false); } }
Кстати, вам не следует использовать == для сравнения строк, используйте .equals вместо этого.
Ответ 3
Вам необходимо удалить строки, закрывающие сканер: scan.close();
Это случалось со мной раньше, и это было причиной.
Ответ 4
причина исключения уже была объяснена, однако предлагаемое решение на самом деле не самое лучшее.
Вы должны создать класс, который сохраняет сканер как закрытый, используя шаблон Singleton, который делает этот сканер уникальным в вашем коде.
Затем вы можете реализовать нужные вам методы или создать getScanner ( не рекомендуется ) и управлять им с помощью частного логического значения, что-то вроде alreadyClosed .
Если вы не знаете, как использовать одноэлементный шаблон, вот пример: