我们首先来看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