你不知道的System.out.println()

這篇博客是爲了解釋System.out.println是什麼以及它的工做原理。java

什麼是System.out.println()小程序

System.out.println是一個Java語句,通常狀況下是將傳遞的參數,打印到控制檯。數組

  • System - 是 java.lang包中的一個final類。根據javadoc,「  java.lang.System該類提供的設施包括標準輸入,標準輸出和錯誤輸出流; 訪問外部定義的屬性和環境變量; 一種加載文件和庫的方法; 以及用於快速複製數組等一部分的實用方法... 「
  • out - 是System類的靜態成員,類型爲PrintStream。
    public static final PrintStream out

    他在啓動時就會被實例化,並與主機的標準輸出控制檯進行映射。該流在實例化以後當即打開,並準備接受數據。eclipse

  • println - 是PrintStream類的一個方法。println打印(參數內容+換行符) 到控制檯。PrintStream類中有多個重載的println方法。每一個println是經過調用print方法並添加一個換行符實現的。print方法是經過調用write方法實現的

System.out.println() 結構圖性能

如下是JDK源中System.out.println的骨架結構,和代碼片斷。學習

UML圖spa

部分代碼段:.net

public final class System {
    static PrintStream out;
    static PrintStream err;
    static InputStream in;
    ...
}

public class PrintStream extends FilterOutputStream {
    //out object is inherited from FilterOutputStream class
    public void println() {
    ...
}

 

輸出重定向——改變輸出路徑命令行

’out'對象能夠自定義的。在啓動時由java運行時環境初始化,而且能夠在執行期間由開發人員更改。代替在默認狀況下的標準輸出。當您經過命令行運行程序時,輸出將打印在同一個命令窗口中。咱們可使用setOut方法來改變這種行爲。在如下示例中,我將輸出重定向到同一目錄中的文本文件。翻譯

public class ChangeOut {
	public static void main(String args[]) {
		try {
			System.setOut(new PrintStream(new FileOutputStream("log.txt")));
			System.out.println("Now the output is redirected!");
		} catch(Exception e) {}
	}
}

 

System.out.println性能分析

有一個廣泛的觀念須要你們知道——System.out.println性能並很差。當咱們深刻分析時,其調用順序以下println - > print - > write()+ newLine()。這個順序流是Sun / Oracle JDK的實現。write()和newLine()都包含一個synchronized塊。同步有一點開銷,但更多的是添加字符到緩衝區和打印的開銷更大。

當咱們運行性能分析時,運行多個System.out.println並記錄時間,執行時間會按比例增長。當打印超過50個字符並打印超過50,000行時,性能降低。

固然這一切都取決於咱們使用的場景。不過不管如何請勿使用System.out.println打印日誌( logging)到stdout。

 

System.out.println VS 日誌記錄組件(Log4j等)

System.out.println vs loggers like Log4j

Log4J具備多種記錄級別。若是咱們正在編寫一個小程序,只是爲了實驗/學習目的那麼使用 System.out.println 就很不錯。但當咱們開發生產質量軟件時,咱們應該注意到應該使用記錄組件(log4j等),而且應該避免使用System.out.println。爲何?

  • 靈活性:log4j的記錄器提供了多種記錄級別。咱們能夠相應地分隔日誌信息。例如,X消息只能在PRODUCTION上打印,Y消息應打印在ERROR等上。
  • 可重構性:log4j只需一個參數更改便可關閉全部日誌記錄。
  • 可維護性:想象一下,若是咱們有數百個System.out.println所有經過應用程序散落,那麼在一段時間內將難以維護程序。
  • 粒度:在應用程序中,每一個類均可以有不一樣的記錄器並相應地進行控制。
  • 實用性:在System.out中限制重定向消息的選項,可是若是是記錄器(like log4j),則能夠提供多種選項。咱們甚至能夠建立自定義輸出選項並將其重定向。

因此咱們不該該使用System.out.println進行日誌記錄和調試(logging and debugging)

 

靜態導入來縮短System.out.println

Static Import to Shorten System.out.println()

有時咱們以爲System.out.println是一個很長的語句要打印。靜態導入可能會縮短一點,但不推薦使用,由於它致使可讀性差。我只是使用這種狀況來解釋靜態導入,並避免在下面的狀況下使用它。

import static java.lang.System.out;

public class ShortSOP {
public static void main(String[] args) {
out.println("Hello, world");
}
}

不靜態導入的話直接寫out.println會提示編譯錯誤的。

 

System.err和System.in

做爲相關部分,接下來介紹一下「err」和「in」。'in'與InputStream相關聯。與「out」相對,「in」用於從標準控制檯通用鍵盤獲取輸入。

'err'與PrintStream相關聯,並將參數打印到標準錯誤輸出流。當您使用eclipse等的IDE時,能夠看到「out」和「err」之間的輸出差別。

import java.io.*;

/**
 * Created by zjl on 2017/9/16.
 */
public class InOutErr {
    public static void main(String args[]) {
        try {
        	System.out.println("請輸入一段話");
            BufferedReader reader = new BufferedReader(new InputStreamReader(System.in ));
            String filename = reader.readLine();

            InputStream input = new FileInputStream(filename);
            System.out.println("File opened...");

        } catch (IOException e){
            System.err.println("Where is that file?");
        }
    }
}

打印結果:

 

翻譯自:http://javapapers.com/core-java/system-out-println/

相關文章
相關標籤/搜索