盘一盘 System.out.println()

System.out.println("Hello World")是大部分程序员入门的第一行代码,也可以说是程序员们最熟悉的一行代码。大家真的深入研究过System.out.println()么?今天就来盘一盘System.out.println()!
 

System是个啥?

System作为Java.lang包中一个final类,早在JDK1.0中就存在其中,可谓基石也。
 

再来看看out

out是System中的一个静态的数据成员,但这个成员不是基本类,而是java.io.PrintStream类的对象。out被关键字static修饰,我们可以直接通过System.out来引用,而无须先建立对象。
public final static PrintStream out = null;

out在系统类初始化时被实例化,配置输出在控制台上。

private static void initializeSystemClass() {

    props = new Properties();
    initProperties(props);  // initialized by the VM

    sun.misc.VM.saveAndRemoveProperties(props);


    lineSeparator = props.getProperty("line.separator");
    sun.misc.Version.init();


    FileInputStream fdIn = new FileInputStream(FileDescriptor.in);
    // 获取 FileDescriptor中的静态成员 out并创建对应的文件输出流。out是一个 FileDescriptor对象,它是"标准输出(屏幕)"的标识符。
    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")));

    loadLibrary("zip");

    Terminator.setup();

    sun.misc.VM.initializeOSEnvironment();

    Thread current = Thread.currentThread();
    current.getThreadGroup().add(current);


    setJavaLangAccess();


    sun.misc.VM.booted();
}

//native方法 输出
private static native void setOut0(PrintStream out);

out对象是可以自定义的。开发人员可以在执行期间对out对象进行修改。

public static void setOut(PrintStream out) {
    checkIO();
    setOut0(out);
}

例:修改out输出路径,将结果以文档形式输出

public class ModifyOut {
  public static void main(String args[]) {
       System.setOut(new PrintStream(new FileOutputStream("ModifyOut.txt")));
       System.out.println("out输出已经重定向!");
  }
}

最后是printl()

println()中的传入参数包含了各种各样的参数类型,枚举了一下。
java.io.PrintStream#println()
java.io.PrintStream#println(boolean)
java.io.PrintStream#println(char)
java.io.PrintStream#println(char[])
java.io.PrintStream#println(double)
java.io.PrintStream#println(float)
java.io.PrintStream#println(int)
java.io.PrintStream#println(long)
java.io.PrintStream#println(java.lang.Object)
java.io.PrintStream#println(java.lang.String)

各种参数的println()方法内容大同小异,这里以println(Object x)为例,盘一下println()中都干了些啥。

public void println(Object x) {
    String s = String.valueOf(x);
    synchronized (this) {
        print(s);
        newLine();
    }
}

使用println()方法中的大部分参数,在执行write(s)方法前,通通被转换成String类型。仅char[] 并没有转换成String类型。原因嘛。嘿嘿,String类型就是char[]实现的啊。

public void print(String s) {
    if (s == null) {
        s = "null";
    }
    // 传入的参数在执行write(s)方法前,通通都被转成String类型。
    write(s);
}

操劳多种类型进行String类型转换,就是为了这步write(String s)方法集中统一处理

private void write(String s) {
    try {
        synchronized (this) {    
            //检查确认当前流尚未关闭
            ensureOpen();
            //输出传入的字符串
            textOut.write(s);
            // 刷新此输出流并强制写出所有缓冲的输出字节。
            textOut.flushBuffer();
            charOut.flushBuffer();
            if (autoFlush && (s.indexOf('
') >= 0))
                out.flush();
        }
    }
    catch (InterruptedIOException x) {
        Thread.currentThread().interrupt();
    }
    catch (IOException x) {
        trouble = true;
    }
}
/**
* writeBuffer的大小 默认为1024
*/
private static final int WRITE_BUFFER_SIZE = 1024;

public void write(String str) throws IOException {
    write(str, 0, str.length());
}

public void write(String str, int off, int len) throws IOException {
    synchronized (lock) {
        char cbuf[];
        if (len <= WRITE_BUFFER_SIZE) {
            if (writeBuffer == null) {
                writeBuffer = new char[WRITE_BUFFER_SIZE];
            }
            cbuf = writeBuffer;
        } else {    // Don't permanently allocate very large buffers.
            cbuf = new char[len];
        }
        str.getChars(off, (off + len), cbuf, 0);

        // 输出字符数组(说了这么多,最后处理的还是字符组)
        write(cbuf, 0, len);
    }
}

//  将字符数组buffer写入到输出流中,offset是从buffer中读取数据的起始偏移位置,len是读取的长度。
abstract public void write(char cbuf[], int off, int len) throws IOException;
原文地址:https://www.cnblogs.com/LemonFive/p/11209806.html