通過Java IO流的形式實現(xiàn)鍵盤錄入的疑問
問題描述
問題解答
回答1:因為System.in就是一個靜態(tài)的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屬于標準輸入,可以通過鍵盤或其他方式輸入數(shù)據(jù)。但在源碼里,該對象并沒有(顯式)初始化的方法,通過閱讀源碼,可發(fā)現(xiàn)下面這個方法:
/** * 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);
閱讀注釋可見該方法用于設(shè)定研究setIn0(in),可見該方法是通過調(diào)用底層接口來實現(xiàn)in的設(shè)定,那么在軟件運行時,是如何初始化的呢?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));...}
由此段代碼可知,軟件運行時,先運行靜態(tài)代碼塊,調(diào)用registerNatives()這個底層方法對System類進行初始化,該方法則是調(diào)用initializeSystemClass()方法來初始化System類的,這兩步都是通過VM實現(xiàn)的,然后閱讀initializeSystemClass()這個方法,可見到調(diào)用setIn0,setOut0,steErr0三段代碼,分別初始化了標準輸入,標準輸出,標準錯誤三種輸出流,至此System.in、out、err的初始化流程就都弄清楚了。標記為native的方法是JVM調(diào)用其他代碼實現(xiàn)的功能,這個和底層有關(guān)系,我覺得這個感覺就像是Bootstrap Classloader實際上是C實現(xiàn),但由JVM調(diào)用來加載各個基礎(chǔ)JAR classes相似吧。另外你說InputStream是抽象類(接口),實際上接口類抽象類都可以作為參數(shù),但實現(xiàn)肯定不是他們實現(xiàn)的,他們不能被實現(xiàn),但可以作為參數(shù),畢竟父類出現(xiàn)的地方子類都可以替代,所以這里不存在問題
相關(guān)文章:
1. javascript - 回調(diào)函數(shù)和閉包的關(guān)系2. javascript - 在top.jsp點擊退出按鈕后,right.jsp進行頁面跳轉(zhuǎn),跳轉(zhuǎn)到login.jsp3. android - 哪位大神知道java后臺的api接口的對象傳到前端后輸入日期報錯,是什么情況?求大神指點4. node.js - koa2 如何獲取參數(shù)?5. javascript - 下面的這段算法代碼求解釋6. css3 - 在sublime text里, 如何讓emmet生成的帶前綴css屬性垂直對齊?7. mac連接阿里云docker集群,已經(jīng)卡了2天了,求問?8. javascript - js 有什么優(yōu)雅的辦法實現(xiàn)在同時打開的兩個標簽頁間相互通信?9. java - spring-data Jpa 不需要執(zhí)行save 語句,Set字段就可以自動執(zhí)行保存的方法?求解10. [前端求職必看]前端開發(fā)面試題與答案精選_擴展問題
