关于Java中Scanner对象的hasNext()方法对实现Readable接口的对象中的read()方法调用的探讨

来源:互联网 发布:怎么查看端口号被占用 编辑:程序博客网 时间:2024/06/01 07:40

Java中的Scanner对象,可以扫描String,利用hasNext()和next()可以探测输入流中是否有下一个字符串和获取下一个字符串。


例如:Scanner s = new Scanner("aa bb cc ");
那么对于代码:
while(s.hasNext()){
print(s.next();
}
会输出:
aa
bb
cc
也就是说以空格符来分割字符串。

我们还知道,这个字符串可以换做任意实现了Readable接口的类所生成的对象。这时候我们就需要自己完成继承自Readable中的read()方法。

那么时候,其read()方法是如何被Scanner中的方法所调用的呢?

观察如下代码:

import java.nio.*;import java.util.*;import static net.mindview.util.Print.*;public class RandomWords implements Readable {  private int readCount = 1;//read()执行次数  private int loopCount = 1;  public RandomWords() {  }  public int read(CharBuffer cb) {  if (loopCount == 1){print("进入read执行第" + readCount + "次");readCount++;cb.append("aa bb cc ");loopCount++;return 1;}//仅仅在第一次和第六次给CharBuffer添加3个数据  if (loopCount == 2){print("进入read执行第" + readCount + "次");readCount++;loopCount++;return 1;}//其他的时候返回1,但是并不往Buffer中存放数据,来骗被调用者hasNext(),来观察出现了什么现象  if (loopCount == 3){print("进入read执行第" + readCount + "次");readCount++;loopCount++;return 1;}  if (loopCount == 4){print("进入read执行第" + readCount + "次");readCount++;loopCount++;return 1;}  if (loopCount == 5){print("进入read执行第" + readCount + "次");readCount++;loopCount++;return 1;}    if (loopCount == 6){print("进入read执行第" + readCount + "次");readCount++;cb.append("oo pp qq ");loopCount++;return 1;}  if (loopCount == 7){print("进入read执行第" + readCount + "次");readCount++;loopCount++;return 1;}  if (loopCount == 8){print("进入read执行第" + readCount + "次");readCount++;loopCount++;return 1;}  if (loopCount == 9){print("进入read执行第" + readCount + "次");readCount++;loopCount++;return 1;}  if (loopCount == 10){print("进入read执行第" + readCount + "次");readCount++;return -1;}  return 1;    }  public static void main(String[] args) {  int a = 1;//外层循环的次数  print("1");  Scanner s = new Scanner(new RandomWords())  print("2");      while(s.hasNext()){//这个hasNext()方法会调用read()方法的  print("第" + a + "次执行外层循环");  a ++;  System.out.println("从cb中读出 " + s.next());  }  }} 

上面的执行结果是:
1
2
进入read执行第1次
第1次执行外层循环
从cb中读出 aa
第2次执行外层循环
从cb中读出 bb
第3次执行外层循环
从cb中读出 cc
进入read执行第2次
进入read执行第3次
进入read执行第4次
进入read执行第5次

进入read执行第6次
第4次执行外层循环
从cb中读出 oo
第5次执行外层循环
从cb中读出 pp
第6次执行外层循环
从cb中读出 qq
进入read执行第7次
进入read执行第8次
进入read执行第9次
进入read执行第10次


我们看到了,图中绿色的部分代表的是while(s.hasNext())在不停地调用read()方法,但是返回值一直为false,这是因为我们在read方法中,第2 3 4 5 7 8 9 10次中,都是简单的返回一个1,并不往cb里面添加东西,这样子,s.hasNext()以为有东西可以读,就不停的读取,但是却发生了读不到东西,只好返回false,因此外层循环无法得到执行的现象。




总结:
每当s.hasNext()的时候,readable.read()就会被调用,对于hasNext是否继续读下去和是否返回真值,是分开的,如果read()返回不是-1,那么将继续读下去,因为这相当于被读的数据源告诉自己,还没有结束;但是这并不意味着返回值就是true了,返回值是不是true要亲自到cb中去考察的,这相当于是否读成功了。



原始出处

0 0