3

最近,我在一本关于将用户定义的类作为输入传递给扫描仪的书中读到,但它并没有解释它背后的逻辑。这是程序

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- 

我这里有 2 个问题

  1. 在这里如何调用 read() 函数?
    我的意思是我明白它是以某种方式被隐式调用的,但是从它被调用的地方。

  2. 输出中的单个连字符表明 main 函数中的 while 循环仅迭代一次。但为什么只有一次。我期待像aa-aa-aa-aa-aa-这样的输出

4

2 回答 2

2

在这里如何调用 read() 函数?我的意思是我明白它是以某种方式被隐式调用的,但是从它被调用的地方。

答案在于Scanner方法类的源代码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方法正在调用该Scanner.readinput方法的覆盖版本。

输出中的单个连字符表明 main 函数中的 while 循环仅迭代一次。但为什么只有一次。我期待像aa-aa-aa-aa-aa-这样的输出

因为,字符串中没有空格,aaaaaaaaaa这是默认分隔符模式。结果,所有字符串都在单次迭代中读取。因此,hasNext在第一次迭代后返回 false 并且 while 循环终止。

注意:@Override在覆盖子类中的方法时始终使用注释。

于 2013-08-15T11:04:24.860 回答
0

Scanner 类是用于读取和写入数据的流的包装类。它有一些重载的构造函数。在你的情况下:

public Scanner(Readable source) {
        this(source, WHITESPACE_PATTERN);
    }

被调用。因为interface Readable只有一个方法read(CharBuffer cb)ScannerInputBase是一个 instaceof Readable,所以 Scanner 对象只是调用任何 Readable 传递的 read() 方法。

关于第二点,查看文档next()

从此扫描器中查找并返回下一个完整的令牌。一个完整的标记前后是匹配分隔符模式的输入。此方法可能会在等待输入扫描时阻塞,即使先前调用 hasNext() 返回 true。

使用的默认模式是:

Pattern WHITESPACE_PATTERN = Pattern.compile(
                                                "\\p{javaWhitespace}+");

因此,它是您的扫描仪的 next() 调用,通过多次read()调用一次性读取所有内容。

于 2013-08-15T10:55:22.187 回答