繁体   English   中英

线程“main”中的异常 java.util.NoSuchElementException

[英]Exception in thread "main" java.util.NoSuchElementException

每当我运行它时, chooseCave()函数与in.nextInt()一起工作正常。 当我选择洞穴时,消息以 2 秒的间隔弹出,然后一旦它通过该部分,它就会给我错误:

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

我已经尝试过hasNextLine()hasNextInt() ,当我在main方法中使用while hasNextLine()时,我得到了更多的错误。 当我在chooseCave()方法中使用while hasNextInt()时,它不接受我的输入。

当我在chooseCave()方法中使用if hasNextInt()时,它不接受我对playAgain字符串的输入,并直接进入另一个游戏,但是hasNextInt()布尔值返回false并发送垃圾邮件“Which Cave.. 。“ 无限地。

我已经浏览了错误报告以及 Java 文档和堆栈溢出的类似问题。 请帮忙。

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

}

}

您关闭了关闭底层InputStream的第二个Scanner ,因此第一个Scanner无法再从同一个InputStream读取,并且结果为NoSuchElementException

解决方案:对于控制台应用程序,使用单个ScannerSystem.in读取。

旁白:如前所述,请注意Scanner#nextInt不消耗换行符。 确保在使用Scanner#newLine()再次尝试调用nextLine之前消耗了这些。

请参阅: 不要在单个 InputStream 上创建多个缓冲包装器

nextInt()方法离开\\n (结束行)符号并被nextLine()立即拾取,跳过下一个输入。 您想要做的是对所有内容使用nextLine() ,然后再解析它:

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

这是迄今为止避免问题的最简单方法——不要混合使用“下一个”方法。 仅使用nextLine() ,然后解析int或单独的单词。


此外,如果您只使用一个终端进行输入,请确保您只使用一台Scanner 这可能是例外的另一个原因。


最后一点:将String.equals()函数进行比较,而不是==运算符。

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

只是不要靠近

从您的代码中删除in.close()

Reimeus是正确的,你看到这一点,因为在你的chooseCave in.close()。 另外,这是错误的。

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

您应该使用等于而不是“==”。

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

每个人都解释得很好。 让我回答什么时候应该使用这个类。

什么时候应该使用 NoSuchElementException?

Java 包括几种不同的方法来迭代集合中的元素。 这些类中的第一个 Enumeration 是在JDK1.0中引入的,通常被认为已弃用,以支持更新的迭代类,如 Iterator 和 ListIterator。

与大多数编程语言一样,Iterator 类包含一个hasNext()方法,该方法返回一个布尔值,指示迭代是否有更多元素。 如果hasNext()返回true ,则next()方法将返回迭代中的下一个元素。 与枚举不同,迭代器还有一个remove()方法,它删除通过next()获得的最后一个元素。

虽然 Iterator 被泛化为用于Java Collections Framework中的所有集合, ListIterator更加专业化并且只适用于基于 List 的集合,如ArrayListLinkedList等。 然而, ListIterator增加了更多的功能,允许迭代通过hasPrevious()previous()方法在两个方向上遍历。

根据其他人之前的评论:

您关闭了关闭底层 InputStream 的第二个 Scanner,因此第一个 Scanner 无法再从同一个 InputStream 中读取,并且会产生 NoSuchElementException 结果。

解决方案:对于控制台应用程序,使用单个扫描器从 System.in 读取。

旁白:如前所述,请注意 Scanner#nextInt 不消耗换行符。 确保在尝试使用 Scanner#newLine() 再次调用 nextLine 之前消耗了这些。

请参阅:不要在单个 InputStream 上创建多个缓冲包装器

我想出了这个解决方案。 也许这会帮助某人:

以下代码有效:

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

并且以下代码将不起作用。 此输出与线程相同的问题:

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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