/** * 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. */ public final static InputStream in = null;
First, if there is a security manager, its checkPermission * method is called with a RuntimePermission("setIO") permission * to see if it's ok to reassign the "standard" input stream. *
* * @param in the new standard input stream. * * @throws SecurityException * if a security manager exists and its * checkPermission method doesn't allow * reassigning of the standard input stream. * * @see SecurityManager#checkPermission * @see java.lang.RuntimePermission * * @since JDK1.1 */ public static void setIn(InputStream in) { checkIO(); setIn0(in); } private static native void setIn0(InputStream in);
/* register the natives via the static initializer. * * VM will invoke the initializeSystemClass method to complete * the initialization for this class separated from clinit. * Note that to use properties set by the VM, see the constraints * described in the initializeSystemClass method. */ private static native void registerNatives(); static { registerNatives(); } /** * Initialize the system class. Called after thread initialization. */ private static void initializeSystemClass() { ... FileInputStream fdIn = new FileInputStream(FileDescriptor.in); FileOutputStream fdOut = new FileOutputStream(FileDescriptor.out); FileOutputStream fdErr = new FileOutputStream(FileDescriptor.err); setIn0(new BufferedInputStream(fdIn)); setOut0(new PrintStream(new BufferedOutputStream(fdOut, 128), true)); setErr0(new PrintStream(new BufferedOutputStream(fdErr, 128), true)); ... }
因为System.in就是一个静态的InputStream实例,你可以在java api文档上看看
首先,System.in是一个InputStream类型的对象,在源码里是这样的:
可见System.in属于标准输入,可以通过键盘或其他方式输入数据。
但在源码里,该对象并没有(显式)初始化的方法,通过阅读源码,可发现下面这个方法:
阅读注释可见该方法用于设定
研究setIn0(in),可见该方法是通过调用底层接口来实现in的设定,那么在软件运行时,是如何初始化的呢?
System类中有如下代码:
由此段代码可知,软件运行时,先运行静态代码块,调用registerNatives()这个底层方法对System类进行初始化,该方法则是调用initializeSystemClass()方法来初始化System类的,这两步都是通过VM实现的,然后阅读initializeSystemClass()这个方法,可见到调用setIn0,setOut0,steErr0三段代码,分别初始化了标准输入,标准输出,标准错误三种输出流,至此System.in、out、err的初始化流程就都弄清楚了。
标记为native的方法是JVM调用其他代码实现的功能,这个和底层有关系,我觉得这个感觉就像是Bootstrap Classloader实际上是C实现,但由JVM调用来加载各个基础JAR classes相似吧。
另外你说InputStream是抽象类(接口),实际上接口类抽象类都可以作为参数,但实现肯定不是他们实现的,他们不能被实现,但可以作为参数,毕竟父类出现的地方子类都可以替代,所以这里不存在问题