Java 多重扫描器
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19766566/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Java Multiple Scanners
提问by Ryan Gibson
I have a class that creates multiple Integer
objects and puts them into a LinkedList
as shown below:
我有一个创建多个Integer
对象并将它们放入 a 的类LinkedList
,如下所示:
public class Shares<E> implements Queue<E> {
protected LinkedList<E> L;
public Shares() {
L = new LinkedList<E>();
}
public boolean add(E price) {
System.out.println("How many of these shares would you like?");
Scanner scanInt;
scanInt = new Scanner(System.in);
Integer noShares = scanInt.nextInt();
for (int i = 0; i < noShares; i++) {
L.addLast(price);
}
scanInt.close();
return true;
}
}
I have an application that scans for the input "add" from the console and if found, invokes the method add
as shown below:
我有一个应用程序从控制台扫描输入“add”,如果找到,则调用add
如下所示的方法:
public class Application {
private static Scanner scan;
public static <E> void main(String[] args) {
Queue<Integer> S = new Shares<Integer>();
scan = new Scanner(System.in);
System.out.println("Please type add");
String sentence = scan.nextLine();
while (sentence.equals("quit") == false) {
if (sentence.equals("add")) {
System.out
.println("What price would you like to buy your shares at?");
S.add((Integer) scan.nextInt());
} else
System.exit(0);
sentence = scan.nextLine();
}
}
}
The application should allow the user to enter "add" as many times as they wish but the error "no line found" appears after the add
method has been invoked.
应用程序应允许用户根据需要多次输入“add”,但在add
调用该方法后会出现错误“no line found” 。
I'm guessing this is because the Scanner
in the method, has not been closed and then reopened when needed. Is this what is wrong with the program and if so, how would I go about fixing it?
我猜这是因为Scanner
方法中的 没有关闭,然后在需要时重新打开。这是程序的问题吗?如果是,我将如何修复它?
Please note, this program is not finished, as I will be adding a selling method that sells these shares. That is why I am using a while loop.
请注意,该程序尚未完成,因为我将添加一种出售这些股票的出售方法。这就是我使用 while 循环的原因。
回答by Peter Lawrey
Having multiple wrappers for any stream is a great way to really confuse yourself. I suggest you only ever wrap a stream once unless you really know what you are doing.
为任何流使用多个包装器是一种真正混淆自己的好方法。我建议你只包装一次流,除非你真的知道你在做什么。
The simplest way to do this is to use a singleton in this case as it wraps another singleton (the best is to pass around the Scanner as an argument)
最简单的方法是在这种情况下使用单例,因为它包装了另一个单例(最好是将 Scanner 作为参数传递)
public class Application {
// use this Scanner in all you other code, don't create another one.
static final Scanner scan = new Scanner(System.in);
public static <E> void main(String[] args) {
Im guessing this is because the scanner in the method has not been closed
我猜这是因为方法中的scanner没有关闭
Once you close a stream it closes the underlying stream and you can't use it again. Only close System.in if you want to prevent it being used again.
关闭流后,它会关闭底层流,您将无法再次使用它。如果您想防止再次使用它,请仅关闭 System.in。
how would I go about fixing it?
我将如何修复它?
The best solution is to have all your Scanner use in one place, one method or one class. You have your main() do all the interaction with the user and pass the values to your data structure. Having objects which initialise themselves is a bad practice to get into and if you start doing this, it will plague you for the rest of your development days ;) (Seriously you will see this done again and again and its often a nightmare)
最好的解决方案是在一个地方、一种方法或一个类中使用所有扫描仪。您让 main() 完成与用户的所有交互并将值传递给您的数据结构。拥有初始化自己的对象是一种不好的做法,如果你开始这样做,它将在你剩下的开发日中困扰你;)(说真的,你会一次又一次地看到这一切,这通常是一场噩梦)
BTW Never exit a program without explanation. Calling System.exit(0);
without even an error message is also a nightmare. I once worked on a project which has 260 calls to System.exit() often without an error message, you can imagine how much fun it is to diagnose a server just stopping for no apparent reason.
BTW 永远不要在没有解释的情况下退出程序。System.exit(0);
甚至没有错误消息的调用也是一场噩梦。我曾经参与过一个项目,该项目对 System.exit() 进行了 260 次调用,通常没有错误消息,您可以想象诊断服务器无缘无故停止是多么有趣。
回答by nelly
A first mistake is that this line of code
第一个错误是这行代码
scanInt.close();
closes the System.in, not just the scanInt object. This means that after the first call to add, the scan object will only consume the input it already has and then you'll receive a NoSuchElementException: Remove this line.
关闭 System.in,而不仅仅是 scanInt 对象。这意味着在第一次调用 add 之后,扫描对象将只使用它已有的输入,然后您将收到 NoSuchElementException: Remove this line。
Now, if you replace the last line you have with this
现在,如果你用这个替换你的最后一行
sentence = scan.nextLine();
System.out.println("sentence: \"" + sentence + "\"");
you will see that the last input you get before exiting is an empty String. So in the next loop you enter the else statement and your program stops execution. You can fix this problem by adding the following:
您将看到退出前获得的最后一个输入是一个空字符串。因此在下一个循环中您输入 else 语句并且您的程序停止执行。您可以通过添加以下内容来解决此问题:
scan.nextLine(); // consume the first always empty String...
System.out.println("Please type add");
sentence = scan.nextLine(); // and then get the actual value
However, I will agree with Peter that you should not use multiple wrappers. Consider passing the Scanner object as an argument in the Shares class contractor.
但是,我同意 Peter 的观点,您不应该使用多个包装器。考虑将 Scanner 对象作为参数传递给 Shares 类承包商。
回答by freedev
Have multiple scanners (on same stream) is a very bad practice, because scanners consume the stream they share.
拥有多个扫描器(在同一流上)是一种非常糟糕的做法,因为扫描器会消耗它们共享的流。
I've verified while debugging the source code and looking at Scanner
class I've found:
我在调试源代码并查看Scanner
我发现的类时进行了验证:
- a reference to the source input stream
- a internal private buffer used to hold input.
- 对源输入流的引用
- 用于保存输入的内部私有缓冲区。
So when a scanner instance consume its stream, basically it just read a bunch of bytes (1024) and the stream's position is moved ahead.
因此,当扫描器实例消耗其流时,基本上它只是读取一堆字节(1024)并且流的位置向前移动。
For example when the nextLine()
method is invoket, behind the scenes the source.read()
copy the result into the private buffer.
例如,当nextLine()
方法被调用时,在幕后source.read()
将结果复制到私有缓冲区中。
Obviously the state of other Scanner becomes corrupted (invalid).
显然其他扫描仪的状态已损坏(无效)。
Try to debug the Java source code yourself and/or look at the method Scanner.readInput()
.
尝试自己调试 Java 源代码和/或查看方法Scanner.readInput()
。