答案是“因为扫描仪处于状态”。
查看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类的实例的情况下,这种类型的结构在面向对象的语言中变得更加麻烦。