我知道,在java中,抽象類只能被引用,但不能被初始化。 InputStream
是一個抽象類,並在System
類我注意到下面的聲明,如何初始化InputStream類型的System.in?
static InputStream in;
因此,如果我們想要的代碼System.in.read()
工作,可變in
需要進行初始化。
我的問題是java如何做到這一點?如果InputStream
是抽象的,其他一些子類應該擴展它。默認哪個類是?
我知道,在java中,抽象類只能被引用,但不能被初始化。 InputStream
是一個抽象類,並在System
類我注意到下面的聲明,如何初始化InputStream類型的System.in?
static InputStream in;
因此,如果我們想要的代碼System.in.read()
工作,可變in
需要進行初始化。
我的問題是java如何做到這一點?如果InputStream
是抽象的,其他一些子類應該擴展它。默認哪個類是?
幸運的是,它很容易檢查對象System.in
的類型是指:
System.out.println(System.in.getClass().getName());
版畫(對我來說):
java.io.BufferedInputStream
所以這是一個BufferedInputStream
。它是什麼包裝?那麼,
Field f = FilterInputStream.class.getDeclaredField("in");
f.setAccessible(true);
Syystem.out.println(f.get(System.in).getClass().getName());
打印(再次,對我來說):
java.io.FileInputStream
所以System.in
是FileInputStream
包裹在BufferedInputStream
。這很有意義,如果你認爲大多數操作系統都像文件一樣對待控制檯。實際上,這個FileInputStream
從FileDescriptor.in
所指的「文件」中讀取。
通過搜索引用FileDescriptor.in
,我發現那裏System.in被初始化代碼:私人靜態方法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
可能是由本地代碼調用,因爲似乎沒有引用它。
你有我的感激之情。 – 2015-02-08 04:23:29
它在'(hotspot)src/share/vm/runtime/thread.cpp'的'JvmtiExport :: post_vm_start'中被調用。 – Yuning 2016-10-26 17:26:52
在System
類的聲明如下:
public final static InputStream in = null;
請大家看看javadocs:
「標準」 輸入流。這個流已經打開並準備好供應輸入數據 。通常,此流對應於鍵盤輸入 或主機環境或用戶指定的另一個輸入源。
這意味着當JVM啓動時,System.in由Java運行時初始化。關於你的問題:
如果InputStream是抽象的,其他一些子類應該擴展它。 默認那個類是?
很多類擴展InputStream
類,如:FileInputStream,ObjectInputStream,...
在JVM引導過程中發生的一些黑魔法會將in
初始化爲正確的值。
例如,在Java 8中,它是通過名爲initializeSystemClass()
的私有方法完成的。 javadoc評論說:
「初始化系統類,線程初始化後調用。」
閱讀source code瞭解血淋淋的細節。他們可以改變從一個Java版本到下一個...雖然沒出現的Java 6和Java 8
Notes之間發生了變化:
的System.in,out,err
實際的設定由完成native
方法。這些本地方法也被System.set{In,Out,Err}
方法使用。
在Java 6到Java 8中,in
字段被初始化爲包含FileInputStream
的BufferedInputStream
。有趣的是,輸入流通常不適用於文件系統中的對象。
它可能會出現在你沒有源代碼的地方 - 無論是在內部類中(Sun.package中的某個地方)還是JVM本身。 – immibis 2015-02-08 04:01:51