I'm new to using Java, but I have some previous experience with C#. The issue I'm having comes with reading user input from console.
I'm running into the "java.util.NoSuchElementException" error with this portion of code:
payment = sc.next(); // PromptCustomerPayment function
I have two functions that get user input:
If I don't call PromptCustomerQty then I don't get this error, which leads me to believe I am doing something wrong with scanner. Below is my full code sample. I appreciate any help.
public static void main (String[] args) { // Create a customer // Future proofing the possabiltiies of multiple customers Customer customer = new Customer("Will"); // Create object for each Product // (Name,Code,Description,Price) // Initalize Qty at 0 Product Computer = new Product("Computer","PC1003","Basic Computer",399.99); Product Monitor = new Product("Monitor","MN1003","LCD Monitor",99.99); Product Printer = new Product("Printer","PR1003x","Inkjet Printer",54.23); // Define internal variables // ## DONT CHANGE ArrayList<Product> ProductList = new ArrayList<Product>(); // List to store Products String formatString = "%-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); } public static void PromptCustomerQty(Customer customer, ArrayList<Product> ProductList) { // Initiate a Scanner Scanner scan = new Scanner(System.in); // **** VARIABLES **** int qty = 0; // Greet Customer System.out.println("Hello " + customer.getName()); // Loop through each item and ask for qty desired for (Product p : ProductList) { do { // Ask user for qty System.out.println("How many would you like for product: " + p.name); System.out.print("> "); // Get input and set qty for the object qty = scan.nextInt(); } while (qty < 0); // Validation p.setQty(qty); // Set qty for object qty = 0; // Reset count } // Cleanup scan.close(); } public static void PromptCustomerPayment (Customer customer) { // Initiate Scanner Scanner sc = new Scanner(System.in); // Variables String payment = ""; // 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(); }
The NoSuchElementException is thrown by Scanner class, Iterator interface, Enumerator interface, and StringTokenizer class. These classes have accessors' methods to fetch the next element from an iterable. They throw NoSuchElementException if the iterable is empty or has reached the maximum limit.
Solution. The solution to this exception is to check whether the next position of an iterable is filled or empty. You should only move to this position if the check returns that the position is not empty.
The NoSuchElementException in Java is thrown when one tries to access an iterable beyond its maximum limit. This means that, this exception is thrown by various accessor methods to indicate that the element being requested does not exist .
hasNextInt() method returns true if the next token in this scanner's input can be interpreted as an int value in the default radix using the nextInt() method. The scanner does not advance past any input.
This has really puzzled me for a while but this is what I found in the end.
When you call, sc.close()
in first method, it not only closes your scanner but closes your System.in
input stream as well. You can verify it by printing its status at very top of the second method as :
System.out.println(System.in.available());
So, now when you re-instantiate, Scanner
in second method, it doesn't find any open System.in
stream and hence the exception.
I doubt if there is any way out to reopen System.in
because:
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.**
The only good solution for your problem is to initiate the Scanner
in your main method, pass that as argument in your two methods, and close it again in your main method e.g.:
main
method related code block:
Scanner scanner = new Scanner(System.in); // Ask users for quantities PromptCustomerQty(customer, ProductList, scanner ); // Ask user for payment method PromptCustomerPayment(customer, scanner ); //close the scanner scanner.close();
Your Methods:
public static void PromptCustomerQty(Customer customer, ArrayList<Product> ProductList, Scanner scanner) { // no more scanner instantiation ... // no more scanner close } public static void PromptCustomerPayment (Customer customer, Scanner sc) { // no more scanner instantiation ... // no more scanner close }
Hope this gives you some insight about the failure and possible resolution.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With