Reputation: 2589
I know that, in java, abstract class can only be referenced but not initialized. InputStream
is an abstract class, and in the System
class I noticed the following declaration,
static InputStream in;
So if we want the code System.in.read()
to work, variable in
needs to be initialized.
My question is how java does that? If InputStream
is abstract, some other subclass should have extend it. Which class is that by default?
Upvotes: 1
Views: 1726
Reputation: 58868
Luckily, it is easy to check the type of object System.in
refers to:
System.out.println(System.in.getClass().getName());
prints ( for me ):
java.io.BufferedInputStream
so it's a BufferedInputStream
. What is it wrapping? Well,
Field field = FilterInputStream.class.getDeclaredField("in");
field.setAccessible(true);
System.out.println(field.get(System.in).getClass().getName());
prints (again, for me):
java.io.FileInputStream
So System.in
is a FileInputStream
wrapped in a BufferedInputStream
. This makes sense, if you consider that most operating systems treat the console the same way as a file. In fact, this FileInputStream
reads from the "file" referred to by FileDescriptor.in
.
By searching for references to FileDescriptor.in
, I found the code where System.in is initialized: in the private static method System.initializeSystemClass
:
FileInputStream fdIn = new FileInputStream(FileDescriptor.in);
FileOutputStream fdOut = new FileOutputStream(FileDescriptor.out);
FileOutputStream fdErr = new FileOutputStream(FileDescriptor.err);
setIn0(new BufferedInputStream(fdIn));
setOut0(newPrintStream(fdOut, props.getProperty("sun.stdout.encoding")));
setErr0(newPrintStream(fdErr, props.getProperty("sun.stderr.encoding")));
initializeSystemClass
is probably called by native code, as there seem to be no references to it.
Upvotes: 5
Reputation: 718826
There is some black magic that happens behind the scenes during JVM bootstrap to initialize in
to the correct value.
For example, in Java 8 it is done by a private method called initializeSystemClass()
. The javadoc comment says:
"Initialize the system class. Called after thread initialization."
Read the source code for the gory details. They could vary from one Java version to the next ... though they don't appear to have changed between Java 6 and Java 8.
Notes:
The actual setting of System.in,out,err
is done by native
methods. These native methods are also used by the System.set{In,Out,Err}
methods.
In Java 6 through Java 8, the in
field is initialized to a BufferedInputStream
that wraps a FileInputStream
. Interestingly, the input stream is typically not for a "file" ... in the sense of an object in the / a file system.
Upvotes: 4
Reputation: 5021
The declaration in the System
class is the following:
public final static InputStream in = null;
Please take a look at the javadocs:
The "standard" input stream. This stream is already open and ready to supply input data. Typically this stream corresponds to keyboard input or another input source specified by the host environment or user.
It means that System.in is initialized by the Java runtime when a JVM starts up. Regarding your question:
If InputStream is abstract, some other subclass should have extend it. Which class is that by default?
Many classes extends the InputStream
class, like: FileInputStream, ObjectInputStream, ...
Upvotes: -1