Scanner类如何与用户定义的类一起使用作为输入

时间:2013-08-15 10:43:45

标签: java java.util.scanner

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

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- 

我在这里有两个问题

  1. 如何调用read()函数?
    我的意思是我理解它隐含地称为某种方式,但从它被调用的地方。

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

2 个答案:

答案 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()调用一次性读取所有内容。