通过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是抽象类(接口),实际上接口类抽象类都可以作为参数,但实现肯定不是他们实现的,他们不能被实现,但可以作为参数,毕竟父类出现的地方子类都可以替代,所以这里不存在问题
相关文章:
1. javascript - 微信jssdk ios下自定义onMenuShareAppMessage 分享失效,Android分享成功2. 老师百度网盘分享一下WampServer的包啊,我们下载几kb要下载一天的.3. vue.js - linux下怎么使用vue-cli的vue命令4. html5 - 在移动端设置font-size小于12px。line-height的问题5. 前端 - CSS中的过度受限在W3C规范里面的哪一部分有提到?6. javascript - iconfont字体图标旋转7. javascript - 关于trasform后的坐标计算的问题8. javascript - 相邻元素有空格,如何找出它相邻的上一个兄弟元素,而不是#text?9. css3 - 自己做的CSS网格系统里面为什么两个div不能同行?10. javascript - vuex 参数绑定问题求解
