我知道我在这里有点冒险,但我似乎不明白为什么不能创建两次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:我故意关闭了我的第一个扫描仪,并创建了一个新的对象,只是为了理解这个问题。
4条答案
按热度按时间4xrmg8kj1#
它很简单,每个输入只需要创建一个扫描仪。扫描仪使用nextline()方法逐行读取。最后检查条件hasnext(),以便找出参数。
试试这个
输出类
eeq64g8w2#
这个答案集中在
close()
操作以及为什么没有选择从System.in
如果一个扫描器示例之前关闭了它,因为上面的答案已经给出了正确的信息。只是好奇而已。扫描仪
当扫描仪关闭时,如果输入源实现可关闭接口,它将关闭输入源。如果没有外部同步,扫描仪对于多线程使用是不安全的。
您应该为每个要从中读取的源创建一个scanner示例。
如果必须共享同一个示例,那么应该实现同步机制,因为它不是线程安全的。
其他答案已经指出,
close()
是个“危险”的行动。system.in close()
让我们假设一下
System.in
已指定为源。这是最接近的方法
InputStreamReader
```public void close() throws IOException
{
synchronized (lock)
{
// Makes sure all intermediate data is released by the decoder.
if (decoder != null)
decoder.reset();
if (in != null)
in.close();
in = null;
isDone = true;
decoder = null;
}
}
/**
/
public void close() throws IOException {
/ empty */
}
public InputStreamReader(InputStream in)
{
super(in);
this.in = in;
...
}
protected Reader(Object lock)
{
if (lock == null) {
throw new NullPointerException();
}
this.lock = lock;
}
public String nextLine() {
if (hasNextPattern == linePattern())
return getCachedResult();
clearCaches();
}
c7rzv4ha3#
实际上,这里有两件不同的事情。
你应该创建一个
Scanner
每个输入源。例如,一个Scanner
对于每个不同的输入文件,一个用于System.in
,每个不同的套接字输入流一个。原因是(正如chrylis指出的)不同的
Scanner
预读扫描仪的输入源。如果操作未使用字符,则不会将其放回输入源。相反,它们是由Scanner
,并为下一个Scanner
要使用的操作。因此,如果您有两个扫描器试图从同一输入源读取数据,其中一个可能会窃取另一个的输入。这就是为什么要开多家公司的真正原因
Scanner
上的对象System.in
很糟糕。不是你提出的“冗余”论点。有一点冗余从根本上说没有什么错。。。尤其是如果它简化了应用程序。但是扫描器争夺输入可能会导致意外的行为/错误。第二个问题是当你
close()
一Scanner
这也会关闭输入源。对你来说,这意味着你要关门了
System.in
. 然后你创造了第二个Scanner
阅读(现已关闭)System.in
.当你试图给我们一个
Scanner
从一个封闭的System.in
,这将导致NoSuchElementException
.如果你没打电话
close()
一开始Scanner
,您的代码可能已经工作,但这将取决于您在第一个Scanner
.人们在说
Scanner
不可克隆。他们是对的。
pkbketx94#
你应该只创建一个
Scanner
每个输入流。除此之外,扫描仪会提前读取,因此会消耗比实际返回的更多的输入(这就是它如何知道,例如,输入hasNextInt()
以此类推。)如果您有多个输入流(例如处理多个文件),那么创建多个扫描器是完全明智的,但是
System.in
应该只有一个扫描仪使用它。