1. 程式人生 > >thinking in java (二十六) ----- System.out.println("hello world")原理

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