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

观察如下代码:

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中去考察的,这相当于是否读成功了。



原始出处

你可能感兴趣的:(java,Scanner,readable)