扫描仪应该只实例化一次吗?如果是这样,为什么会这样?
我知道我在这里冒险,但我似乎无法理解为什么我们不能只创建 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:我故意关闭了我的第一个扫描仪并创建了一个新对象只是为了理解这个问题。
回答
这里实际上有两件不同的事情发生。
-
您应该
Scanner
为每个输入源创建一个。例如,一个Scanner
用于每个不同的输入文件,一个用于System.in
,一个用于每个不同的套接字输入流。原因是(正如 Chrylis 指出的)是
Scanner
在扫描仪的输入源上预读的各种方法。如果操作未消耗字符,则不会将它们放回输入源。相反,它们由 缓冲Scanner
,并保留以供下一个Scanner
操作使用。所以如果你有两个扫描器试图从同一个输入源读取,一个可能会窃取用于另一个的输入。这就是打开多个对象不好的真正原因。不是您提出的“冗余”论点。一点点冗余从根本上来说并没有错……特别是如果它简化了应用程序。但是竞争输入的扫描器可能会导致意外的行为/错误。
Scanner
System.in
-
第二个问题是,当你
close()
a时Scanner
,也关闭了输入源。在您的情况下,这意味着您正在关闭
System.in
. 然后您正在创建第二个Scanner
读取(现已关闭)System.in
。当您尝试让我们
Scanner
从封闭的a中读取时System.in
,会导致 aNoSuchElementException
。
因此,如果您没有调用close()
第一个Scanner
,您的代码可能会起作用,但这取决于您在第一个Scanner
.
人们说
Scanner
不可克隆。
他们是正确的。