简体   繁体   中英

Exception in thread "main" java.util.NoSuchElementException

Whenever I run this, the chooseCave() function works fine with the in.nextInt() . When I choose the cave, the messages pop up at 2-second intervals, and then as soon as it gets past that part, it gives me the error:

Exception in thread "main" java.util.NoSuchElementException: No line found
    at java.util.Scanner.nextLine(Unknown Source)
    at Dragon.main(Dragon.java:81)

I have tried hasNextLine() and hasNextInt() , and when I use while hasNextLine() in the main method, I get a ton more errors. When I use while hasNextInt() in the chooseCave() method, it doesn't accept my input.

When I use if hasNextInt() in the chooseCave() method, it doesn't accept my input for the playAgain string, and goes straight into another game, but then the hasNextInt() boolean returns false and it spams "Which cave..." infinitely.

I've gone through the error reports and the Java-docs and Stack Overflow's with similar problems. Please help.

import java.util.Scanner;
public class Dragon {

public static void displayIntro() {
    System.out.println("You are in a land full of dragons. In front of you, ");
    System.out.println("You see two caves. In one cave, the dragon is friendly");
    System.out.println("and will share his treasure with you. The other dragon");
    System.out.println("is greedy and hungry, and will eat you on sight");
    System.out.println(' ');
}

public static int chooseCave() {
    Scanner in = new Scanner(System.in);
    int cave = 0;
    while (cave != 1 && cave != 2) {
        System.out.println("Which cave will you go into? (1 or 2)");

        cave = in.nextInt();

    }
    in.close();
    return cave;
} 

public static void checkCave(int chosenCave) {
    System.out.println("You approach the cave...");
    try
       {
       // Sleep at least n milliseconds.
       // 1 millisecond = 1/1000 of a second.
       Thread.sleep( 2000 );
       }
    catch ( InterruptedException e )
       {
       System.out.println( "awakened prematurely" );
       }
    System.out.println("It is dark and spooky...");
    try
       {
       // Sleep at least n milliseconds.
       // 1 millisecond = 1/1000 of a second.
       Thread.sleep( 2000 );
       }
    catch ( InterruptedException e )
       {
       System.out.println( "awakened prematurely" );
       }
    System.out.println("A large dragon jumps out in front of you! He opens his jaws and...");
    try
       {
       // Sleep at least n milliseconds.
       // 1 millisecond = 1/1000 of a second.
       Thread.sleep( 2000 );
       }
    catch ( InterruptedException e )
       {
       System.out.println( "awakened prematurely" );
       }

    double friendlyCave = Math.ceil(Math.random() * 2);

    if (chosenCave == friendlyCave) {
        System.out.println("Gives you his treasure!");
    }
    else {
        System.out.println("Gobbles you down in one bite!");
    }



}
public static void main(String[] args) {
    Scanner inner = new Scanner(System.in);
    String playAgain = "yes";
    boolean play = true;
    while (play) {
        displayIntro();
        int caveNumber = chooseCave();
        checkCave(caveNumber);
        System.out.println("Do you want to play again? (yes or no)");
        playAgain = inner.nextLine();
        if (playAgain == "yes") {
            play = true;
        }
        else {
            play = false;
        }
    }
    inner.close();

}

}

You close the second Scanner which closes the underlying InputStream , therefore the first Scanner can no longer read from the same InputStream and a NoSuchElementException results.

The solution: For console apps, use a single Scanner to read from System.in .

Aside: As stated already, be aware that Scanner#nextInt does not consume newline characters. Ensure that these are consumed before attempting to call nextLine again by using Scanner#newLine() .

See: Do not create multiple buffered wrappers on a single InputStream

The nextInt() method leaves the \\n (end line) symbol and is picked up immediately by nextLine() , skipping over the next input. What you want to do is use nextLine() for everything, and parse it later:

String nextIntString = keyboard.nextLine(); //get the number as a single line
int nextInt = Integer.parseInt(nextIntString); //convert the string to an int

This is by far the easiest way to avoid problems--don't mix your "next" methods. Use only nextLine() and then parse int s or separate words afterwards.


Also, make sure you use only one Scanner if your are only using one terminal for input. That could be another reason for the exception.


Last note: compare a String with the .equals() function, not the == operator.

if (playAgain == "yes"); // Causes problems
if (playAgain.equals("yes")); // Works every time

simply don't close in

remove in.close() from your code.

Reimeus is right, you see this because of in.close in your chooseCave() . Also, this is wrong.

if (playAgain == "yes") {
      play = true;
}

You should use equals instead of "==".

if (playAgain.equals("yes")) {
      play = true;
}

Everyone explained pretty well on it. Let me answer when should this class be used.

When Should You Use NoSuchElementException?

Java includes a few different ways to iterate through elements in a collection. The first of these classes, Enumeration, was introduced in JDK1.0 and is generally considered deprecated in favor of newer iteration classes, like Iterator and ListIterator.

As with most programming languages, the Iterator class includes a hasNext() method that returns a boolean indicating if the iteration has anymore elements. If hasNext() returns true , then the next() method will return the next element in the iteration. Unlike Enumeration, Iterator also has a remove() method, which removes the last element that was obtained via next() .

While Iterator is generalized for use with all collections in the Java Collections Framework , ListIterator is more specialized and only works with List-based collections, like ArrayList , LinkedList , and so forth. However, ListIterator adds even more functionality by allowing iteration to traverse in both directions via hasPrevious() and previous() methods.

Based on the earlier comment by someone else:

You close the second Scanner which closes the underlying InputStream, therefore the first Scanner can no longer read from the same InputStream and a NoSuchElementException results.

The solution: For console apps, use a single Scanner to read from System.in.

Aside: As stated already, be aware that Scanner#nextInt does not consume newline characters. Ensure that these are consumed before attempting to call nextLine again by using Scanner#newLine().

See: Do not create multiple buffered wrappers on a single InputStream

I have came up with this solution. Perhaps this will help someone:

the following code WORKS:

import java.util.Scanner;

public class Main {

    private static String func(Scanner in) {
        String input = "";
        in = new Scanner(System.in).useDelimiter("\n");
        input = in.next();
        System.out.println("UserInput: " + input);

        return input;
    }

    public static void main(String[] args) {

        Scanner in = new Scanner(System.in);

        String s;
        s = func(in);
        System.out.println("Main: " + s);

        s = func(in);
        System.out.println("Main: " + s);
    }
}

and the following code WILL NOT WORK. this output the same problem as the thread:

import java.util.Scanner;

public class Main {

    private static String func() {
        String input = "";
        Scanner s = new Scanner(System.in);
        input = s.nextLine();
        System.out.println("UserInput: " + input);

        input = s.nextLine();
        System.out.println("UserInput: " + input);

        s.close();

        return input;
    }

    public static void main(String[] args) {

        String s;
        s = func();
        System.out.println("Main: " + s);

        s = func();
        System.out.println("Main: " + s);
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM