天天看點

Java筆試中的輸入輸出(2)hasNext()和hasNextLine()hasNextLine()和nextLine()

hasNext()和hasNextLine()

hasNextLine()和nextLine()

hasNextLine()方法

同樣看一些說明文檔中對方法的描述:

Java筆試中的輸入輸出(2)hasNext()和hasNextLine()hasNextLine()和nextLine()

如果在掃描器的輸入中還有另外一行,就傳回true,事實上同樣沒有傳回fasle的情況,如果沒有另外一行了,就會阻塞,等待你的輸入。

兩個容易出錯的問題

問題1:hasNextLine() 和 next() 混用

首先看一下以下代碼:如果啟動代碼後,在控制台輸入

hello回車

,會進入幾次while循環的代碼段中呢?

import java.util.Scanner;

public class ScannerTest {
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        while (scan.hasNextLine()) {
            String str = scan.next();
            System.out.println(str);
        }
    }
}
           

表面上來說,隻會進入1次,首先在

while (scan.hasNextLine())

中阻塞,系統等待我的輸入,輸入

hello回車

之後,自然就進入了循環體,str擷取到了hello,并把他輸出,又重新回到while循環的判斷語句中,因為我們隻輸入了一行,是以輸入流中沒有另外一行了,就會重新阻塞在while循環判斷中,系統等待我的輸入。然而這種了解是錯誤的

實際上,會進入2次while循環,并且,第二次會在

String str = scan.next()

處阻塞,等待我們的輸入。

這要怎麼了解呢?個人是這麼了解的,當我們第一次輸入

hello回車

之後,

while (scan.hasNextLine())

判斷為真,就第一次進入了循環體中,

String str = scan.next();

讀取輸入流中一個字元串,遇到空白(回車、空格、Tab)就截止,是以str被指派為

hello

,再次回到

while (scan.hasNextLine())

因為這裡是

hasNextLine()

而在hello後面可以想象成有一個

\n

,那麼

hasNextLine()

會認為

\n

是一個空行,再次判斷為真,進入循環體,但是

next()

會自動忽略第一個有效字元前的空白符,是以會在

String str = scan.next();

阻塞,等待我們的輸入。

如果我們将循環的判斷語句改為

while (scan.hasNext())

,那麼就隻會進入一次while循環,第二次會阻塞在

while (scan.hasNext())

中,系統等待我們的輸入。

為此,大家可以通過下圖的方式進行調試,一步一步的跟蹤代碼:

Java筆試中的輸入輸出(2)hasNext()和hasNextLine()hasNextLine()和nextLine()

簡單來說:

  • 在讀取完了有效字元之後,hasNext() 會認為之後沒有有效字元了,就會阻塞
  • 而hasNextLine(),會把有效字元後面的

    \n

    作為新的一行,傳回真

如果我們用這種代碼錯誤的認為他隻會進入一次while循環,并且在

while (scan.hasNextLine())

處等待我新的輸入,在oj系統上就會報錯。

為此解決的辦法就是,要統一起來,前面用hasNextLine() 後面就用nextLine()。

問題2:緊跟在next() 後面的 nextLine() 是無法讀取到有效值的

同樣舉個例子:

import java.util.Scanner;

public class ScannerTest {
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        String str1 = scan.next();
        System.out.println(str1);
        String str2 = scan.nextLine();
        System.out.println(str2);
    }
}
           

這個代碼我想實作的功能是,在

String str1 = scan.next();

擷取一個字元串(沒有空格),在

String str2 = scan.nextLine();

擷取一行字元串(可能包含空格)。但是無法實作這個功能,當我們輸入

hello回車

之後,程式就結束了。str2是一個空串(長度 = 0)

這是因為:當我在流中輸入

hello回車

之後,str1讀走了hello,雖然hasNextLine() 會把後面的\n當成是1行,是以不會在

String str2 = scan.nextLine();

這邊阻塞,但是這一行是為空的,是以nextLine()捕獲到的就是一個空串。

下面的代碼更好地說明了這個問題

import java.util.Scanner;

public class ScannerTest {
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);

        String str1 = scan.next();
        System.out.println(str1);
        if (scan.hasNextLine())
            System.out.println(1);
        String str2 = scan.nextLine();
        if (str2 != null && str2.equals(""))
            System.out.println(3);
    }
}
           
Java筆試中的輸入輸出(2)hasNext()和hasNextLine()hasNextLine()和nextLine()

提示:

  • scan.hasNext()和scan.next() 在是否阻塞上有同樣的效果,如果此時流中存在有效字元,那麼前者傳回true,後者讀取這個有效字元(串);反之,如果目前流中不存在有效字元(串),前者不會傳回false,而是會阻塞,後者同樣會阻塞,等待輸入。
  • 但是還是建議在next()擷取之前用hasNext()進行判斷。
  • 問題1和問題2的關鍵在于,當有效字元輸入完了之後,用hasNextLine()判斷的話會傳回True,這就導緻了在oj環境下,問題1進入循環,但是next()讀不到值報錯;問題2中next()讀完了之後(有效字元讀完了之後),nextLine()會直接讀取而不會阻塞。