thinking in java (二十六) ----- System.out.println("hello world")原理
我們首先來看System.out.println("hello world")的流程,先看看System類中out的定義
public final class System {
...
public final static PrintStream out = null;
...
}
從中,我們可以發現:
1,out是System中的一個靜態變數
2,out是PrintStream物件,PrintStream中有很多過載的println方法
我們知道了out是PrintStream物件,接下來看它是如何被初始化的,是怎麼和螢幕輸出關聯的?
首先我們System類,先看其中的初始化方法,initialSystemClass()方法。
原始碼如下:
1 private static void initializeSystemClass() { 2 3 props = new Properties(); 4 initProperties(props); // initialized by the VM 5 6 sun.misc.VM.saveAndRemoveProperties(props); 7 8 lineSeparator = props.getProperty("line.separator"); 9 sun.misc.Version.init(); 10 11 FileInputStream fdIn = new FileInputStream(FileDescriptor.in); 12 FileOutputStream fdOut = new FileOutputStream(FileDescriptor.out); 13 FileOutputStream fdErr = new FileOutputStream(FileDescriptor.err); 14 setIn0(new BufferedInputStream(fdIn)); 15 setOut0(new PrintStream(new BufferedOutputStream(fdOut, 128), true)); 16 setErr0(new PrintStream(new BufferedOutputStream(fdErr, 128), true)); 17 18 loadLibrary("zip"); 19 20 Terminator.setup(); 21 22 sun.misc.VM.initializeOSEnvironment(); 23 24 Thread current = Thread.currentThread(); 25 current.getThreadGroup().add(current); 26 27 setJavaLangAccess(); 28 29 sun.misc.VM.booted(); 30 }
我們只需要關注12 15行程式碼:即
FileOutputStream fdOut = new FileOutputStream(FileDescriptor.out);
setOut0(new PrintStream(new BufferedOutputStream(fdOut, 128), true));
將這兩句話細分,可以劃分為以下幾步:
1,FileDescriptor fd = FileDescriptor.out;
2,FileOutputStream fdOut = new FileOutputStream(fd);
3,BufferedOutputStream bufOut = new BufferedOutputStream(fdOut, 128);
4, PrintStream ps = new PrintStream(bufout, true);
5,setOut0(ps);
說明:
1,獲取FileDescriptor類中的靜態成員out,out是FileDescriptor物件,他實際上是“標準輸出(螢幕)”的標誌符。
2,建立“標準輸出(螢幕)”對應的“檔案輸出流,
3,建立檔案輸出流對應的緩衝輸出流,目的是為了給檔案輸出加上緩衝的功能
4,建立緩衝輸出流對應的“列印輸出流”,目的是為了給“緩衝輸出流”,如print,ptintln等,使其能夠方便列印輸出
5,執行setOut0(ps);
第五步的的setOut(ps),檢視System.class中的原始碼,關於setOut0()的申明,如下:
private static native void setOut0(PrintStream out);
從中我們可以發現setOut()是一個native方法,我們可以檢視原始碼(我看不懂)可以總結,setOut(PrintStream ps)的作用是:將ps設定為System類的out靜態變數。
前面已經說過,FileDescriptor.out就是機器的標準輸出的檔案標誌符,我們可以通俗地將檔案標誌符理解為:FileDescriptor就是代表的“標準輸出”,因此在initialSystemClass()中,上面的五步就是講FileDescriptor.out封裝了起來,封裝後的System.in既有緩衝功能,又有便利的操作介面,如print,println,ptintf。
原文:http://www.cnblogs.com/skywang12345/p/io_17.html