目錄
- 問題一:循環建立Scanner對象并使用close()方法
- 問題二:循環輸入校驗時不處理校驗失敗的部分
- 其他用法
問題一:循環建立Scanner對象并使用close()方法
菜鳥想要用Scanner達到循環輸入的目的,沒有直接百度而是“自以為是”的在循環裡寫建立Scanner類,并且還“體貼”的在使用完畢後close()掉:
for(int i = 0; i < 3; i++) {
System.out.println("第"+(i+1)+"次輸入");
Scanner sc = new Scanner(System.in);
String strInput = sc.next();
sc.close();
}
然而,在循環到第二次的時候就不對了:
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIyZuBnL5UTM3IzNxIjM3AzMwEjMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
試了半天,最後老實問度娘:Scanner + java.util.NoSuchElementException
原來是因為第二次循環sc.next()找不到下一個元素,找不到的原因是因為上次循環結束時關閉了System.in。
“System.in 在java中是靜态變量,目前類所有的scanner對象共享它,當一個scanner對象執行close()操作後,其他所有的scanner對象都不可用了。”
—— Scanner 的執行錯誤NoSuchElementException
正确姿勢:
Scanner sc = new Scanner(System.in);
for(int i = 0; i < 3; i++) {
System.out.println("第"+(i+1)+"次輸入");
String strInput = sc.next();
}
sc.close();
把開頭結尾丢循環外面就對了~
問題二:循環輸入校驗時不處理校驗失敗的部分
之是以要循環輸入是因為想要做校驗,輸入不通過就繼續輸入。比如:判斷輸入的類型;輸入是否在規定範圍内等。
判斷輸入的類型可以用Scanner的hasNextInt()、hasNextDouble()等,其中hasNext()就是判斷是否有下一次輸入的内容,不管類型,其他的都是判斷是否有下一個相應類型的輸入。比如輸入一個整數:
Scanner sc = new Scanner(System.in);
while(true) {
System.out.println("請輸入一個整數:");
if(sc.hasNextInt()) {
int intInput = sc.nextInt();
System.out.println("輸入的整數為:"+intInput);
break;
}
}
sc.close();
問題不是有值怎樣,而是沒有值怎麼處理,如果輸入的是"abc",我以為的結果是接着下一次輸入就好了,然而事實是:
進入了死循環…我在sc.hasNextInt()那行打了斷點,發現進入if之後,第一次程式會等待我輸入内容,後面就不等我輸入了,直接判斷不符合if條件。
“遇到hasNext()時,Scanner也會阻塞,等待你輸入,等你輸入後傳回true。檢視jdkapi,你會發現該方法當Scanner緩存區中有值可讀時,會傳回true,若沒有,會一直阻塞等待你輸入。”
“hasNextInt()函數大體意思表示scanner目前的标記的輸入是否為int,并不會自動的移動标記。”
——《Scanner的hasNext、hasNextInt用法》
也就是說,若輸入的是整數,進入if代碼塊,執行了hasNextInt()方法會改變讀取的标記位置;若輸入的不是整數,沒有執行類似hasNext()之類的方法,緩存區裡将會放着上次的輸入内容,進而一直if條件不滿足。
解決方法就是:hasNext()之類的方法,要和next()之類的方法搭配使用:
Scanner sc = new Scanner(System.in);
while(true) {
System.out.println("請輸入一個整數:");
if(sc.hasNextInt()) {
int intInput = sc.nextInt();
System.out.println("輸入的整數為:"+intInput);
break;
}else {
sc.next();
}
}
sc.close();
其他用法
- 終止輸入:要麼在控制台 ctrl+z,要麼約定一個輸入的字元串作為終止符,寫在循環條件裡
- 實際上每行輸入結尾應該都帶着"\n",通過nextInt()、nextDouble()等隻能讀取數值,是不包含那個回車的,這時候再接一個nextLine()你将成功擷取到一個回車~
- next()方法由第一個有效字元(非空格,非換行符) 開始,到第一個分隔符或結束符(空格或換行符) 結束,進而獲得第一個掃描到的不含空格、換行符的單個字元串。換言之,如果想要擷取帶空格的内容,就用nextLine()
-
關于光标cursor位置:
nextInt() - 光标位置在數值後面,"\n"前面;
next() - 光标指向本行;
nextLine() - 光标指向下一行