NOTE: problem doesn't appear when we run your code from console/terminal via java [options] [MainClass]
so if this is valid solution for you you can stop reading here. Rest of this answer is for people who are using some IDEs to run their code.
Problem
Most IDEs are using javaw.exe
instead of java.exe
to run Java code (see image below).
Difference between these two programs is that javaw
runs Java code without association with current terminal/console (which is useful for GUI applications), and since there is no associated console window System.console()
returns null
. Because of that System.console().readLine()
ends up as null.readLine()
which throws NullPointerException
since null
doesn't have readLine()
method (nor any method/field).
But just because there is no associated console, it doesn't mean that we can't communicate with javaw
process. This process still supports standard input/output/error streams, so IDEs process (and via it also we) can use them via System.in
, System.out
and System.err
.
This way IDEs can have some tab/window and let it simulate console.
For instance when we run code like in Eclipse:
package com.stackoverflow;
public class Demo {
public static void main(String[] args) throws Exception {
System.out.println("hello world");
System.out.println(System.console());
}
}
we will see as result
which shows that despite javaw.exe
not having associated console (null
at the end) IDE was able to handle data from standard output of the javaw
process System.out.println("hello world");
and show hello world
.
General solution
To let user pass information to process use standard input stream (System.in
). But since in
is simple InputStream
and Stream
s are meant to handle binary data it doesn't have methods which would let it easily and properly read data as text (especially if encoding can be involved). That is why Readers
and Writers
ware added to Java.
So to make life easier and let application read data from user as text you can wrap this stream in one of the Reader
s like BufferedReader
which will let you read entire line with readLine()
method. Unfortunately this class doesn't accept Streams
but Reader
s, so we need some kind of adapter which will simulate Reader and be able to translate bytes to text. But that is why InputStreamReader
exists.
So code which would let application read data from input stream could look like
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.print("Hello. Please write your name: ");
String name = br.readLine();
System.out.println("Your name is: "+name);
Preferred/simplest solution - Scanner
To avoid this magic involving converting Stream to Reader you can use Scanner
class, which is meant to read data as text from Streams and Readers.
This means you can simply use
Scanner scanner = new Scanner(System.in);
//...
String name = scanner.nextLine();
to read data from user (which will be send by console simulated by IDE using standard input stream).