最近,我读了一本关于将用户定义的类作为输入传递给扫描仪的书,但它没有解释它背后的逻辑。这是程序
import java.nio.CharBuffer;
import java.util.Random;
import java.util.Scanner;
class ScannerInputBase implements Readable
{
private int count;
Random rand = new Random();
ScannerInputBase(int count) { this.count = count; }
public int read(CharBuffer cb) //read is a method in Readable interface
{
if(count-- == 0)
return -1;
for(int i=0;i<2;i++)
{ cb.append('a'); }
return 1;
}
}
public class ScannerInput {
public static void main (String args[]) {
Scanner input = new Scanner(new ScannerInputBase(5));
while(input.hasNext())
{
print(input.next()+"-");
}
}
}
它的输出是
aaaaaaaaaa-
我在这里有两个问题
如何调用read()函数?
我的意思是我理解它隐含地称为某种方式,但从它被调用的地方。
输出中的单个连字符表示while函数中的while循环仅迭代一次。但为什么只有一次。我期待输出像aa-aa-aa-aa-aa -
答案 0 :(得分:2)
如何调用read()函数?我的意思是我明白了 隐式地以某种方式调用,但是从它被调用的地方调出。
答案在于方法Scanner
的{{1}}类的源代码:
next()
将我们带到public String next() {
....
while (true) {
.....
if (needInput)
readInput();
...
}
}
方法,其定义如下:
readInput
我们看到private void readInput() {
......
try {
n = source.read(buf);
} catch (IOException ioe) {
.....
}
.....
}
方法正在调用readInput
对象的read
方法,该方法是source
类的实例,并作为参数传递给Reader
} Scanner
创建对象时的构造函数。
现在,因为您已将Scanner
的子类的对象作为参数传递给Reader
构造函数。而且,你已经在你的班级中覆盖了Scanner
方法,所以
read(CharBuffer)
方法正在调用read
方法的重写版本。
输出中的单个连字符表示main函数中的while循环仅迭代一次。但为什么只有一次。我期待输出像aa-aa-aa-aa-aa -
因为,字符串Scanner.readinput
中没有空格,这是默认的分隔符模式。因此,所有字符串都在单次迭代中读取。因此,aaaaaaaaaa
在第一次迭代后返回false,而while循环终止。
注意:在覆盖方法时始终使用
hasNext
注释 在子类中。
答案 1 :(得分:0)
Scanner类是围绕流读取和写入数据的包装类。它有一些overloaded constructors。在你的情况下:
public Scanner(Readable source) {
this(source, WHITESPACE_PATTERN);
}
被调用。因为interface Readable
只有一个方法read(CharBuffer cb)
,ScannerInputBase
是一个可读的实例,所以Scanner对象只调用readable传递的read()方法。
关于第二点,请查看next()
查找并返回此扫描仪的下一个完整令牌。一个 完整标记之前和之后是匹配的输入 分隔符模式。此方法可能在等待输入时阻塞 扫描,即使之前的hasNext()调用返回true。
使用的默认模式是:
Pattern WHITESPACE_PATTERN = Pattern.compile(
"\\p{javaWhitespace}+");
所以,你的扫描仪的next()调用,通过多次read()
调用一次性读取所有内容。