關於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中去考察的,這相當於是否讀成功了。






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