【问题标题】:how Scanner class works with user defined class as inputScanner 类如何使用用户定义的类作为输入
【发布时间】:2013-08-15 10:43:44
【问题描述】:

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

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

【问题讨论】:

    标签: java java.util.scanner


    【解决方案1】:

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

    答案在于方法next()Scanner类的源代码:

    public String next() {
        ....
        while (true) {
         .....
         if (needInput)
             readInput();
         ...
        }
    }
    

    这将我们带到readInput方法,其定义如下:

    private void readInput() {
        ......
         try {
             n = source.read(buf);
         } catch (IOException ioe) {
        .....
         }
        .....
     }
    

    我们看到readInput 方法正在调用source 对象的read 方法,该对象是Reader 类的实例,并在Scanner 的对象创建期间作为参数传递给Scanner 构造函数. 现在,由于您已将Reader 的子类对象作为参数传递给Scanner 构造函数。而且,您已经在您的班级中覆盖了read(CharBuffer) 方法,所以 read 方法的覆盖版本正在由 Scanner.readinput 方法调用。

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

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

    注意:在重写方法时始终使用 @Override 注释 在子类中。

    【讨论】:

      【解决方案2】:

      Scanner 类是用于读取和写入数据的流的包装类。它有几个overloaded constructors。在你的情况下:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-03-13
        • 2014-11-16
        • 2011-01-28
        • 2014-05-26
        • 2014-02-19
        • 1970-01-01
        相关资源
        最近更新 更多