为什么我们需要Scanner类的实例才能在Java上获得输入?


10

Java是面向对象的,但是,为什么我们需要从Scanner类创建一个对象来获取输入?next()例如,方法不能只是静态的吗?

C相我很简单,因为你只需要使用scanf()gets()fgets()。我确定Java开发人员有理由创建Scanner类,但是这比仅具有正常功能来完成工作更好吗?

我发现此链接似乎在问相同的问题,但答案仅与

“您需要创建一个对象,因为它不是静态的” ...

我的猜测是:由于Java是面向对象的,因此他们决定将所有输入方法放在一个类中。他们没有执行静态方法,因此您可以在不同的对象中拥有各种不同的源(键盘输入,文件输入...)?

如果有人可以编辑问题以使其听起来更加清晰,我将不胜感激!

Answers:


34

答案是“因为扫描仪处于状态”。

查看java.util.Scanner代码,您将看到许多私有字段,例如缓冲区及其相关信息,Matcher,Pattern,输入源,有关源是否关闭,类型的信息。最后匹配的内容,有关是否是否有效匹配的信息,用于数字的基数,语言环境(有关您正在使用.还是,作为千位分隔符的信息)以及其自己的LRU缓存(用于最近使用的模式)的信息,有关遇到的最后一个异常的信息,有关解析数字的某些信息,有关解析布尔值的一些信息,有关解析整数的更多信息……我想就是这样。

如您所见,多数民众赞成在那是一个很大的文本块。那就是扫描仪的状态。为了使Scanner成为静态类,该状态需要存储在其他位置。使用C的方式实际上并没有太多状态。你有一个fscanf。FILE维护有关其位置的某种状态(但是每次调用都需要传递该状态fscanf)。如果有错误,你必须处理它(然后你开始编写代码,看起来像这样) -这不能告诉你类似的信息:“我在等一个整数,但发现一个字符串。”

当人们从理论上看静态的Scanner时-所有状态都在类外部维护,它没有封装在类中。其他代码位可以修改这些变量。当其他代码可以修改类的状态时,就很难推理出该类在任何给定情况下会做什么。

您可能会编写类似的ScannerState { Locale loc; ... }代码,并产生导致以下结果的代码:

ScannerState state = new ScannerState(a whole lot of arguments);
int foo = Scanner.nextInt(state);

但是,这比起首先将状态封装在Scanner对象内(而不需要传递状态)要麻烦得多。

最后,扫描器实现了该接口,Iterator<String>这意味着人们可以在以下代码中使用它:

Scanner in = new Scanner(someFile);
whie(in.hasNext()) { ... }

在无法获取Scanner类的实例的情况下,这种类型的结构在面向对象的语言中变得更加麻烦。


1
尽管InputStream也具有状态,而不仅仅是Scanner,但您编写的所有内容都是绝对正确的。如果输入来自控制台(如C语言),则无需传递任何参数即可开始接受输入。我想有人做过这样的方式与其他流如何完成其中的一致性需要国家。
尼尔

@Neil的InputStream等同于FILE*(位置状态)C.
棘轮怪物

1
扫描程序实现Iterator-否Iterable。无法在增强型for循环中使用Scanner。
turbanoff

精确地@ratchetfreak。那就是“状态” FileInputStreams必须具有的内容,但不适用于来自控制台的输入,因为它在技术上已经开放。
尼尔

1
@turbanoff谢谢您对此表示欢迎。我已经改正了。

7

简短的回答:你没有。您无需使用Scanner实例即可获取用户输入。
例如:https : //docs.oracle.com/javase/tutorial/essential/io/cl.html
http://alvinalexander.com/blog/post/java/java-source-code-read-command-line输入


String orgName = (new BufferedReader(new InputStreamReader(System.in))).readLine();与使用a相比,这令人费解Scanner,而且创建的不是一个对象而是两个对象的新实例,只是立即将其丢弃。
菲利普

2
@ Philipp,1)很麻烦,但肯定是另一种选择; 2)如果您立即丢弃实例,那么您做错了(或者您实际上只需要从控制台读取一行)。
Arturo TorresSánchez2015年

您不需要扫描仪即可读取输入。您也不需要InputStreamReader,也不需要BufferedReader。您可以在System.in上使用“原始”流,就像在C中一样。Scanner只是使用该流的一种非常舒适的方法。
Traubenfuchs
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.