zoukankan      html  css  js  c++  java
  • 盘一盘 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;
  • 相关阅读:
    .NET XmlNavigator with Namespace
    编程要素
    【FOJ】1962 新击鼓传花游戏
    【POJ】1389 Area of Simple Polygons
    【POJ】2482 Stars in Your Window
    【HDU】3265 Posters
    【HDU】1199 Color the Ball
    【HDU】3642 Get The Treasury
    【HDU】4027 Can you answer these queries?
    【HDU】1542 Atlantis
  • 原文地址:https://www.cnblogs.com/LemonFive/p/11209806.html
Copyright © 2011-2022 走看看