web-dev-qa-db-fra.com

Exception dans le thread "principal" Java.util.NoSuchElementException

Chaque fois que je lance ceci, la fonction chooseCave() fonctionne très bien avec la fonction in.nextInt(). Lorsque je choisis la grotte, les messages apparaissent à des intervalles de 2 secondes, puis dès qu'elle dépasse cette partie, cela me donne l'erreur:

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

J'ai essayé hasNextLine() et hasNextInt(), et lorsque j'utilise while hasNextLine() dans la méthode main, j'obtiens une tonne d'erreurs supplémentaires. Lorsque j'utilise while hasNextInt() dans la méthode chooseCave(), il n'accepte pas mon entrée.

Lorsque j'utilise if hasNextInt() dans la méthode chooseCave(), il n'accepte pas mon entrée pour la chaîne playAgain et va directement dans un autre jeu, mais ensuite le hasNextInt() boolean renvoie false et il spams "Which cave ..." à l'infini.

J'ai parcouru les rapports d'erreur et les documents Java et les débordements de pile avec des problèmes similaires. Veuillez aider.

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();

}

}
8
Isaac Smith

Vous fermez le second Scanner qui ferme le InputStream sous-jacent, donc le premier Scanner ne peut plus lire à partir du même InputStream et d'un NoSuchElementException résultats.

La solution: pour les applications de console, utilisez un seul Scanner pour lire dans System.in.

Mis à part: Comme indiqué précédemment, sachez que Scanner#nextInt Ne consomme pas de caractères de nouvelle ligne. Assurez-vous que ceux-ci sont consommés avant de réessayer d'appeler nextLine en utilisant Scanner#newLine().

Voir: Ne créez pas plusieurs wrappers tamponnés sur un seul InputStream

12
Reimeus

La méthode nextInt() laisse le symbole \n (Ligne de fin) et est immédiatement reprise par nextLine(), sautant la prochaine entrée. Ce que vous voulez faire, c'est utiliser nextLine() pour tout, et l'analyser plus tard:

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

C'est de loin le moyen le plus simple d'éviter les problèmes - ne mélangez pas vos "prochaines" méthodes. Utilisez uniquement nextLine() puis analysez ints ou des mots séparés par la suite.


Assurez-vous également d'utiliser un seul Scanner si vous n'utilisez qu'un seul terminal pour l'entrée. Cela pourrait être une autre raison de l'exception.


Dernière remarque: comparez un String avec la fonction .equals(), pas l'opérateur ==.

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

ne fermez pas

supprimez in.close() de votre code.

2
Abhishek Goel

Reimeus a raison, vous voyez cela à cause de in.close dans votre chooseCave (). C'est également faux.

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

Vous devez utiliser égal au lieu de "==".

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

Tout le monde s’y est bien expliqué. Permettez-moi de vous dire quand utiliser cette classe.

Quand devez-vous utiliser NoSuchElementException?

Java comprend plusieurs façons différentes d'itérer les éléments d'une collection. La première de ces classes, Enumeration, a été introduite dans JDK1.0 Et est généralement considérée comme obsolète au profit des classes d'itération plus récentes, comme Iterator et ListIterator.

Comme avec la plupart des langages de programmation, la classe Iterator inclut une méthode hasNext() qui retourne un booléen indiquant si l'itération a plus d'éléments. Si hasNext() renvoie true, alors la méthode next() renverra l'élément suivant dans l'itération. Contrairement à l'énumération, Iterator possède également une méthode remove(), qui supprime le dernier élément obtenu via next().

Alors que Iterator est généralisé pour être utilisé avec toutes les collections dans Java Collections Framework, ListIterator est plus spécialisé et ne fonctionne qu'avec les collections basées sur des listes, comme ArrayList, LinkedList , et ainsi de suite. Cependant, ListIterator ajoute encore plus de fonctionnalités en permettant à l'itération de se déplacer dans les deux directions via les méthodes hasPrevious() et previous().

0
Sushant Chaudhari