我只是想知道为什么是java。util。扫描器实现java。util。迭代器?
Scanner
实现删除方法,并抛出一个不支持的操作异常。
但是一个类在实现接口时,不应该履行接口的契约吗?
实现迭代器
并添加引发异常的方法有什么用?
为什么不直接避免接口的实现并保持简单呢?
有人可能会争辩说,它的定义是为了让可能扩展
Scanner
的类能够实现该方法,就像AbstractList有一个add方法抛出一个UnsupportedOperationException
。但是AbstractList
是一个abstract
类,而Scanner
是一个final
类。
这不是一个糟糕的设计实践吗?
有关官方答案,请参阅集合框架概述。向下滚动至底部以查看设计目标。
为了保持核心接口的数量较小,这些接口不试图捕捉诸如可变性、可修改性和可调整性等细微差别。相反,核心接口中的某些调用是可选的,使实现能够抛出UnsupportedOperationException
,以指示它们不支持指定的可选操作。集合实现者必须清楚地记录实现支持哪些可选操作。
正如前面的答案所指出的那样,集合框架可以通过将其接口分解为许多更小的接口来支持Liskov substation。为了尽量减少框架中核心接口的数量,考虑并拒绝了这种方法。
我会说是的,这是一个设计缺陷。该漏洞位于迭代器中。此问题可能与试图创建不可变的集合
实现的问题属于同一类别。
它违反了接口隔离原则,并迫使开发人员在JavaDocs中包含一个角落大小写(臭名昭著的Unsupport tedoperationExc0019
),以避免违反Liskov Subsittion原则。您可以在集合#移除方法中找到这一点。
我相信设计可以通过分解接口来改进,将hasNext()
和Next()
分离到一个新的(不可变的)接口中,并让(可变的)Iterator
接口从中派生:
interface Traversable<E> {
boolean hasNext();
E next();
}
interface Iterator<E> extends Traversable<E> {
void remove();
}
final class Scanner implements Traversable<String> {
}
当然可以用更好的名字。请不要因为我糟糕的命名选择而写下这篇文章。
Scanner
不是遍历集合的迭代器。但是扫描器的想法是为它提供“扫描”的输入,从某种意义上说,这是对某些东西(字符串
中的字符)的迭代。
我可以理解为什么
Scanner
将实现Iterator
(您要求使用用例)。例如,如果您想创建自己的Iterable
类型来迭代指定分隔符的String
:
class ScannerWrapper implements Iterable<E> {
public Scanner scanner;
public ScannerWrapper(Scanner scanner) {
this.scanner = scanner;
}
public Iterator<String> iterator() {
return scanner;
}
}
Scanner scanner = new Scanner("one,two,three");
scanner.useDelimiter(",");
ScannerWrapper wrapper = new ScannerWrapper(scanner);
for(String s : wrapper) {
System.out.println(s);
}
但是,如果JDK支持
Traversable
类型并允许增强的循环接受Traversable
项,这也会起作用,因为以这种方式从集合中删除可能会抛出一个ConnettModificationExc0019
,这导致使用迭代器相反。
那么这是一个好的设计吗?不。它违反了ISP,导致合同混乱。这只是一种巨大的代码味道。真正的问题是该语言缺乏对不变性的支持,这应该允许开发人员指定行为是否应该改变状态,从而使行为契约不再具有可变性。或者类似的东西。。
JDK中充满了这样的东西(糟糕的设计选择,比如为数组暴露
length
,尝试ImmutableMap
),现在更改它会导致代码中断。
我写了一个小程序,它检查字符串是否按照用户输入的字母顺序排序,并用空白隔开一行。它的工作,这是伟大的,但我不明白的是,为什么我可以使用扫描器创建数组时,大小还没有设置。任何见解都将不胜感激。
因此,我是一个新的Java程序员,我正试图弄清楚为什么一段代码不能工作。我遇到的问题是“String interests=input.nextLine();”这一行,它跳过了用户的输入并跳转到下一个System.out,所以它只显示“Your Profile...”。在允许用户输入任何数据之前。抱歉,如果这是一个愚蠢的问题,我是很新的!
问题内容: 我的Java作业有问题。我遇到了意外的异常,特别是: java.util.NoSuchElementException:找不到行 我正在使用,该程序不断读取任何内容,并重复“无效格式”异常文本。如果输入正确的值,则第一部分通过,然后该部分立即进入此异常。如果输入的值不正确,则它将开始循环异常。 这是我的代码: 问题答案: 您关闭了多个库,这些库关闭了底层库,因此另一个库将不再从同一库和
问题内容: 使用Scanner类中的useDelimiter时遇到一些问题。 如果我有这个输入 美国广播公司 输出将是 AB 然后等到我键入另一个“-”以打印出最后一个字符 但是,如果我没有用户输入数据,而是将字符串插入到Scanner中,则代码将起作用。原因是什么?如何解决?我不想使用StringTokenzier 问题答案: 如果没有等待您输入另一个,则将错误地假定您已完成输入。 我的意思是,
我做了一个程序,要求3个整数来输出三角形的类型。所有内容都成功运行和编译,但是,在要求用户查看是否要再次循环的部分,联机编译器会输出错误: 异常线程"main"java.util.NoSuchElement异常在java.util.Scanner.throwFor(Scanner.java:838)在java.util.Scanner.next(Scanner.java:1347)在Assignm
问题内容: 我不明白为什么第15行不做任何输入,将不胜感激:3 输出量 请输入您的问题的第一个数字!2552所以您选择了2552选择您的第二个数字41您选择了第二个数字41现在输入ur运算符 由于某种原因,输出在最后一行结束并停止,并且不接收任何信息! 问题答案: 您需要在调用行的后面立即调用,原因是仅要求下一个整数不会占用输入中的整个行,因此您需要通过调用来跳至输入中的下一个新行字符。 每次您需