System.out.println

简介: This Java tutorial is to explain what System.out.println is and how it works. It is love at first type.

from: https://javapapers.com/core-java/system-out-println/

System.out.println

This Java tutorial is to explain what System.out.println is and how it works. It is love at first type. How many times have we used System.out.println till now? It is one of the most number of times compiled statement in the history of java. We shortly call it SOP.

What is System.out.println

System.out.println is a Java statement that prints the argument passed, into the System.out which is generally stdout.

  • System - is a final class in java.lang package. As per javadoc, "...Among the facilities provided by the System class are standard input, standard output, and error output streams; access to externally defined properties and environment variables; a means of loading files and libraries; and a utility method for quickly copying a portion of an array..."
  • out - is a static member field of System class and is of type PrintStream. Its access specifiers are public final. This gets instantiated during startup and gets mapped with standard output console of the host. This stream is open by itself immediately after its instantiation and ready to accept data.
  • println - is a method of PrintStream class. println prints the argument passed to the standard console and a newline. There are multiple println methods with different arguments(overloading). Every println makes a call to print method and adds a newline. print calls write() and the story goes on like that.

Structure of System.out.println

Following is the skeletal structure of System.out.println in the JDK source. Through this code snippet the essential parts are highlighted and its given for better understanding.

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

public class PrintStream extends FilterOutputStream {
    public void println() {
        //TODO
    }
}

Change out of System.out.println

'out' can be customized. out gets initialized by java runtime environment at startup and it can be changed by developer during execution. Instead of standard output, in default cases when you run a program through command line, the output is printed in the same command window. We can change that behavior using setOut method as below. In the following example, I have redirected the output to a text file in the same directory.

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 vs loggers like Log4j

Log4j has multiple levels for logging. If we are writing a real short program, just for experimental/learning purposes SOPs are fine. When we are developing a production quality software, we should be aware that a logging component should be used and System.out.println should be avoided. Why?

  • Flexibility: a logger like log4j provides different levels for logging. We can separate the log messages accordingly. For example, X messages should be printed only on PRODUCTION, Y messages should be printed on ERROR, etc.
  • Reconfigurability: in just one parameter change we can switch off all the logging statements.
  • Maintainability: imagine if we have hundreds of System.out.println littered all through the application, it would be difficult to maintain the program over a period.
  • Granularity: In an application, every single class can have a different logger and controlled accordingly.
  • Utility: Option for redirecting the message is limited in System.out, but in case of a logger you have appenders which provides numerous options. We can even create a custom output option and redirect it to that.

Having said all the above, we still use System.out.println for logging and debugging. Which should be strictly avoided. This is driven by (bad)habit.

I want to share how a habit became a convention. Its using ‘i’, ‘j’ as index in for-loop. In FORTRAN language, we need not declare integer variables. Variable names that start with i, j, k, l, m and n are integer variables. So, FORTRAN developers named for-loop index with i,j,k and that habit carried on to other languages.

System.out.println and Performance

There is a general notion that System.out.println are bad for performance. When we analyze deeply, the sequence of calls are like println -> print -> write() + newLine(). This sequence flow is an implementation of Sun/Oracle JDK. Both write() and newLine() contains a synchronized block. Synchronization has a little overhead, but more than that the cost of adding characters to the buffer and printing is high.

When we run a performance analysis, run multiple number of System.out.println and record the time, the execution duration increases proportionally. Performance degrades when we print more that 50 characters and print more than 50,000 lines.

It all depends on the scenario we use it. Whatever may be the case, do not use System.out.println for logging to stdout.

Static Import to Shorten System.out.println()

Sometimes we feel System.out.println is a long statement to print. static import may shorten it a bit but it is not recommended, because it results in poor readability. I am just using this situation to explain static import and avoid using it in the below scenario.

import static java.lang.System.out;

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

System.err and System.in

As a related section, I wish to discuss about 'err' and 'in'. 'in' is associated with InputStream. Opposite to 'out', 'in' is used to get input from standard console generally keyboard.

'err' is associated with PrintStream and prints the argument to the standard error output stream. When you use eclipse kind of IDE you can see the difference in ouput between 'out' and 'err'.

public class InOutErr {
    public static void main(String args[]) {
        try {

            BufferedReader reader = new BufferedReader(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?");
        }
    }
}
目录
相关文章
|
5月前
|
Java
System.currentTimeMillis()方法总结
System.currentTimeMillis()方法总结
|
5月前
|
存储 监控 安全
System.getProperty()方法总结
System.getProperty()方法总结
|
5月前
|
Java Linux Windows
system.getproperty详解
system.getproperty详解
print与println的区别
print与println的区别
79 0
“System.out.println(的正确格式
“System.out.println(的正确格式
121 0
使用System.out.println()
使用System.out.println()
77 0
|
Java
Java的System.out.println并不等于C的printf
Java的System.out.println并不等于C的printf
112 0
一次由 Scanner(System.in) 引起的 TLE
继昨天一次由System.out.println() 引起的 MLE&TLE后,今天随机到一道快速选择的题(P1923),又遇到相似的问题,写完快速排序后修改几行代码就得到快速选择的代码,本以为轻松解决问题,然后又莫名其妙的 TLE。
一次由 Scanner(System.in) 引起的 TLE
ZCMU - 1992: Swiss-system tournament
ZCMU - 1992: Swiss-system tournament
110 0
|
缓存 Java Linux
注意了!System.currentTimeMillis() 存在性能问题...
System.currentTimeMillis()是极其常用的基础Java API,广泛地用来获取时间戳或测量代码执行时长等,在我们的印象中应该快如闪电。 但实际上在并发调用或者特别频繁调用它的情况下(比如一个业务繁忙的接口,或者吞吐量大的需要取得时间戳的流式程序),其性能表现会令人大跌眼镜。
注意了!System.currentTimeMillis() 存在性能问题...