扫描仪应该只实例化一次吗?如果是这样,为什么会这样?

我知道我在这里冒险,但我似乎无法理解为什么我们不能只创建 Scanner 类的实例两次。我会添加一个例子以防万一。

import java.util.Scanner;

public class Nope
{
    public static void main(String[] args)
    {
        System.out.println("What's your name?");
        Scanner scanner = new Scanner(System.in);
        String name = scanner.nextLine();
        
        System.out.println("Welcome " + name + "!");
        scanner.close();
        
        // Now 
        System.out.println("where you do live?");
        Scanner sc = new Scanner(System.in);
        String country = sc.nextLine();
        
        System.out.println("That's a lovely place");
        sc.close();
        
    }
}

我得到一个运行时错误,看起来像这样

What's your name?
Kate
Welcome Kate!
Exception in thread "main" where you do live?
java.util.NoSuchElementException: No line found
    at java.base/java.util.Scanner.nextLine(Scanner.java:1651)
    at Nope.main(Nope.java:17)

我知道再次创建同一个类的新对象是没有意义的,鼓励冗余。但我只是认为如果我知道为什么,我的头脑就会清醒,你不也这么认为吗?

'java.util.NoSuchElementException: No line found'是什么意思,人们说扫描仪不可克隆。

PS:我故意关闭了我的第一个扫描仪并创建了一个新对象只是为了理解这个问题。

回答

这里实际上有两件不同的事情发生。

  1. 您应该Scanner为每个输入创建一个。例如,一个Scanner用于每个不同的输入文件,一个用于System.in,一个用于每个不同的套接字输入流。

    原因是(正如 Chrylis 指出的)是Scanner在扫描仪的输入源上预读的各种方法。如果操作未消耗字符,则不会将它们放回输入源。相反,它们由 缓冲Scanner,并保留以供下一个Scanner操作使用。所以如果你有两个扫描器试图从同一个输入源读取,一个可能会窃取用于另一个的输入。

    这就是打开多个对象不好的真正原因。不是您提出的“冗余”论点。一点点冗余从根本上来说并没有错……特别是如果它简化了应用程序。但是竞争输入的扫描器可能会导致意外的行为/错误。ScannerSystem.in

  2. 第二个问题是,当你close()a时Scanner,也关闭了输入源。

    在您的情况下,这意味着您正在关闭System.in. 然后您正在创建第二个Scanner读取(现已关闭)System.in

    当您尝试让我们Scanner从封闭的a中读取时System.in,会导致 a NoSuchElementException

因此,如果您没有调用close()第一个Scanner,您的代码可能会起作用,但这取决于您在第一个Scanner.


人们说Scanner不可克隆。

他们是正确的。


以上是扫描仪应该只实例化一次吗?如果是这样,为什么会这样?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>