To interact with a java application in command line, Scanner is one of the most popular way to implement.
But you know, it also has a mistake that we may easily make.
First, let use it in a simple program:
import java.util.Scanner;
public class Main {
private static String inputString() {
final Scanner scanner = new Scanner(System.in);
String result = "";
if (scanner.hasNextLine()) {
result = scanner.nextLine();
}
return result;
}
public static void main(String[] args) {
System.out.println("input fullName: ");
final String value = inputString();
System.out.println("fullName: " + value);
}
}
/** Output:
input fullName:
John
fullName: hello
**/
Everything works well, yeah!
But, if we change this program to:
import java.util.Scanner;
public class Main {
private static String inputString() {
final Scanner scanner = new Scanner(System.in);
String result = "";
if (scanner.hasNextLine()) {
result = scanner.nextLine();
}
scanner.close();
return result;
}
public static void main(String[] args) {
System.out.println("input fullName: ");
final String value = inputString();
System.out.println("fullName: " + value);
}
}
/** Output:
input fullName:
John
fullName: hello
**/
Uh huh, it also works well, we just close Scanner after used it.
Now we want to input 2 values for first name and last name of user, so we change program to:
import java.util.Scanner;
public class Main {
private static String inputString() {
final Scanner scanner = new Scanner(System.in);
String result = "";
if (scanner.hasNextLine()) {
result = scanner.nextLine();
}
scanner.close();
return result;
}
public static void main(String[] args) {
System.out.println("input firstName: ");
final String firstName = inputString();
System.out.println("input lastName: ");
final String lastName = inputString();
System.out.println("fullName: " + firstName + " " + lastName);
}
}
/** Output:
input firstName:
John
input lastName:
fullName: John
**/
What? The program ended without waiting us to input last name? What happen?
Let’s change a bit of method inputString()
, we don’t check scanner.hasNextLine()
and run it to see what happen:
private static String inputString() {
final Scanner scanner = new Scanner(System.in);
String result = "";
// if (scanner.hasNextLine()) {
result = scanner.nextLine();
// }
scanner.close();
return result;
}
And output:
Now, we can figure out about this problem. The program cannot receive anymore value from user!
But why? The reason is because why had closed it! Yes we had closed the way to receive input from user.
Where? It is:
scanner.close();
But we only closed the scanner of a local variable scanner
, why it affects the whole program?
Because, Scanner works base on System.in
. And when we call scanner.close()
, it also closes InputStream
of System.in
.
When System.in
has closed, we can reuse it in another Scanner
to get input from user. So, when we call scanner.nextLine()
, an exception will occur: NoSuchElementException
in this case.
The problem will also happen when we use it with resource auto-closing with try-catch
like this:
private static String inputString() {
String result = "";
try(Scanner scanner = new Scanner(System.in)){
// if (scanner.hasNextLine()) {
result = scanner.nextLine();
// }
}catch(Exception ex){
ex.printStacktrace();
}
return result;
}
It happens because resource auto-closing will auto call method close
when go out of try-catch block.
Use Scanner in carefully
Never
close
Scanner in your program :)
Let re-write it:
import java.util.Scanner;
public class Main {
private static String inputString() {
final Scanner scanner = new Scanner(System.in);
String result = "";
if (scanner.hasNextLine()) {
result = scanner.nextLine();
}
// scanner.close();
return result;
}
public static void main(String[] args) {
System.out.println("input firstName: ");
final String firstName = inputString();
System.out.println("input lastName: ");
final String lastName = inputString();
System.out.println("fullName: " + firstName + " " + lastName);
}
}
/** Output:
input firstName:
John
input lastName:
Matt
fullName: John Matt
**/
Ok, that is. Now it works well :)