0

I am writing a program to ask user to choose from a menu by inputting in console.

I am new to stackoverflow and java and playing it safe by being as specific as possible. So please excuse me if you find it verbose.

I tested the code with enter "B" at prompts, and the situation is the first iteration is fine, but when the second iteration the program does not block for input any more and give the following error messages in the console(You can find where bug generated just after the comment with asterisks):

Exception in thread "main" java.util.NoSuchElementException
at java.util.Scanner.throwFor(Unknown Source)
at java.util.Scanner.next(Unknown Source)
at MainClass.main(MainClass.java:32)

public class MainClass {

    public static void main(String[] args) {



        AirlineClass theAirline = AirlineClass();
        boolean stopAsking = false;

        while (!stopAsking){
        // display the menu
        String menuContent = "A. Print List of all passengers.\n"
                + "B. Print List of flights.\n"
                + "C. Add a passenger to a flight.\n"
                + "D. Remove a passenger from a flight.\n"
                + "E. Print a List of passengers on a flight.\n"
                + "F. Exit.\n"
                + "Please enter your choice: ";
        System.out.println(menuContent);

        //create a Scanner object for input
        Scanner reader = new Scanner(System.in);
        String choice = reader.next().toUpperCase();




        //*********************************
        // bug here
        reader.close();


        switch (choice) {
        case "A": 
            break;
        case "B":
            System.out.println("You have chose B");
            break;
        case "C":
            break;
        case "D":
            break;
        case "E":
            break;
        case "F":
            System.out.println("Program exits, bye~");
            stopAsking = true;
            reader.close();
            break;
        default:
            System.out.println("Invalid input detected, please try again");
            reader.close();
            break;
        }
    }       
}

After I removed the line reader.close() the program runs just fine.

I thought one possible reasons might be : if I do reader.close(), then every Scanner object I created reference by the name reader with be considered closed already.

It will really be much appreciated if anyone can help me on this. And please do point out if I made some mistakes in the way of asking question.

user207421
  • 289,834
  • 37
  • 266
  • 440
  • Oh, and I forget to point out that the if the control falls into the `default` case, the `reader.close()` will also render the same error. – No harmer Feb 07 '15 at 06:19
  • 2
    You should create the `Scanner` before the loop, so that you can simply use the same object every time you need to get user input. – emlai Feb 07 '15 at 06:20
  • @zenith, thanks. Tried that and it works. I just still want to understand what will be the result of creating multiple object with reference variables of the same name? Does the previous created ones automatically get handled by garbage collection? If this is the case, why would I `.close()` a newly created (and the only) Scanner object cause error? – No harmer Feb 07 '15 at 06:26
  • You don't need (and probably shouldn't) `close()` a `Scanner(System.in)`. See the answers [here](http://stackoverflow.com/questions/14142853/close-a-scanner-linked-to-system-in?rq=1) for explanation. – emlai Feb 07 '15 at 06:28
  • And yes the old ones just get deleted by garbage collection at some point. – emlai Feb 07 '15 at 06:30
  • *Don't* create it inside the loop. There is no loop variant that affects the `Scanner` object creation. – user207421 Feb 07 '15 at 08:44

2 Answers2

0

move the creation of Scanner outside the loop and close just as well. So you can just reuse the same object in each iteration

Scanner reader = new Scanner(System.in);
String choice;
boolean stopAsking = false;
while (!stopAsking) {
    // print menu
    // read data

    choice = reader.next().toUpperCase();

    // switch block with stopAsking = true;
}
reader.close();
mychalvlcek
  • 3,801
  • 1
  • 17
  • 34
  • thanks, it works. However, I just still want to understand what will be the result of creating multiple object with reference variables of the same name? Does the previous created ones automatically get handled by garbage collection? If this is the case, why would I .close() a newly created (and the only) Scanner object cause error? – No harmer Feb 07 '15 at 06:31
0

You should create the Scanner before the loop, so that you can simply use the same object every time you need to get user input.

Also, Scanner(System.in) objects don't need to be close()d and shouldn't be, because close() will also close the System.in stream. Just forget about the close() when using a Scanner(System.in) and you'll be fine. For more information, check the answers here.

Community
  • 1
  • 1
emlai
  • 37,861
  • 9
  • 87
  • 140