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

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中的方法所调用的呢?

观察如下代码:
//: interfaces/RandomWords.java
// Implementing an interface to conform to a method.
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中去考察的,这相当于是否读成功了。






發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章