The basic idea is that next()
returns the next “token” (string of non-whitespace characters) that it finds (skipping any initial whitespace and stopping when it finds another whitespace or the end of the String, whichever comes first). nextLine()
returns everything from the current position (or marker) - including whitespace - until it finds a newline character (or the end of the String, whichever comes first).
To make this easier to reason about, let us take the console out of it and imagine we are just reading from a file with the following contents:
Hello, my name is Bond
James Bond
If we were to put that content into a file called source.txt we could pass it to a Scanner like this:
try (var scanner = new Scanner(new FileInputStream("source.txt"))) {
...
}
NOTE: I am using a try-with-resources block since Scanner is AutoCloseable to make sure we close the resource at the end of the block.
Calling the Scanner’s next()
method would return the String "Hello,"
and leave a marker after "Hello,"
(including the space). In contrast, calling the Scanner’s nextLine()
method will return the String "Hello, my name is Bond"
and leave a marker at the start of the second line (dropping the newline character).
Now things get interesting when we see what happens if we start mixing and matching. If we call next()
once and then next()
again, we will get "my"
for the second string with a marker after "my"
(including the space). In contrast, if we call next()
and then nextLine()
we get " my name is Bond"
(starting with the space after "Hello,"
) for the second string with a marker at the start of the second line (dropping the newline character).
Now let us suppose we get through all of the tokens on the first line by calling next()
five times to pick up the strings "Hello,"
, "my"
, "name"
, "is"
and "Bond"
while leaving the marker at the end of the first line before the newline character. Calling nextLine()
will return an empty string (""
) because the Scanner looks for the next newline character and returns everything preceeding it (which is an empty string since the very next character is a newline character). Try it yourself if you are interested to see the result:
try (var scanner = new Scanner(new FileInputStream("source.txt"))) {
System.out.println("'"+scanner.next()+"'");
System.out.println("'"+scanner.next()+"'");
System.out.println("'"+scanner.next()+"'");
System.out.println("'"+scanner.next()+"'");
System.out.println("'"+scanner.next()+"'");
System.out.println("'"+scanner.nextLine()+"'");
}
What gets tricky when System.in
is the InputStream for our Scanner is that we must type a newline character to return control to the program and finish sending input. So input at the command line always ends with a newline character. Methods like nextByte()
and next()
can basically ignore the newline character because they are looking for the next token and will skip over intervening whitespace (including newline characters). The nextLine()
method is just looking for the next newline character after the marker (which is placed right after the previous token that was found). With that in mind, take a look at my previous answer and see if you now understand the behavior of your program.