您的位置:首页技术文章
文章详情页

通过Java IO流的形式实现键盘录入的疑问

【字号: 日期:2023-12-31 15:18:24浏览:46作者:猪猪

问题描述

通过Java IO流的形式实现键盘录入的疑问

问题解答

回答1:

因为System.in就是一个静态的InputStream实例,你可以在java api文档上看看

回答2:

首先,System.in是一个InputStream类型的对象,在源码里是这样的:

/** * 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;

可见System.in属于标准输入,可以通过键盘或其他方式输入数据。但在源码里,该对象并没有(显式)初始化的方法,通过阅读源码,可发现下面这个方法:

/** * Reassigns the 'standard' input stream. * * <p>First, if there is a security manager, its <code>checkPermission</code> * method is called with a <code>RuntimePermission('setIO')</code> permission * to see if it’s ok to reassign the 'standard' input stream. * <p> * * @param in the new standard input stream. * * @throws SecurityException *if a security manager exists and its *<code>checkPermission</code> 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);

阅读注释可见该方法用于设定研究setIn0(in),可见该方法是通过调用底层接口来实现in的设定,那么在软件运行时,是如何初始化的呢?System类中有如下代码:

/* 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));...}

由此段代码可知,软件运行时,先运行静态代码块,调用registerNatives()这个底层方法对System类进行初始化,该方法则是调用initializeSystemClass()方法来初始化System类的,这两步都是通过VM实现的,然后阅读initializeSystemClass()这个方法,可见到调用setIn0,setOut0,steErr0三段代码,分别初始化了标准输入,标准输出,标准错误三种输出流,至此System.in、out、err的初始化流程就都弄清楚了。标记为native的方法是JVM调用其他代码实现的功能,这个和底层有关系,我觉得这个感觉就像是Bootstrap Classloader实际上是C实现,但由JVM调用来加载各个基础JAR classes相似吧。另外你说InputStream是抽象类(接口),实际上接口类抽象类都可以作为参数,但实现肯定不是他们实现的,他们不能被实现,但可以作为参数,毕竟父类出现的地方子类都可以替代,所以这里不存在问题

标签: java
相关文章: