System.out.println in Java and How it works

System.out.println() is the most used statement in the java language.In this java tutorial we will learn what is System.out.println() and how it works. It is one of the most executed statement in the history of java. We shortly call it SOP. What is System.out.println() this question has been asked many times in java interviews.Let's find out below:

What is System.out.println

In simple words, 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.According to Oracle docs: "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. It is the "standard" output stream. This stream is already open and ready to accept output data.This stream corresponds to display output or another output destination specified by the host environment or user.


  • println- is a method of PrintStream class. println prints the argument passed to the standard console and a newline.There are many println methods with different arguments.Every println internally makes call to print method and adds  a newline. print  method then calls write() method.


  • Structure of System.out.println

    Following is the skeletal structure of System.out.println in the JDK source.


    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() {
        ...
    }
    


    How System.out.println works in Java


    PrintStream class is a comparably higher level class, capable of reading and writing different kinds of data, flushing data and handling errors if exists.

    Let' see how println() is defined in PrintStream.java

    public void println(String x) {
        synchronized (this) {
            print(x);
            newLine();
        }
    }
    

    Following the call stack to print() in PrintStream.java

    public void print(String s) {
        if (s == null) {
            s = "null";
        }
        write(s);
    }
    


    Going one more level and looking at write() in PrintStream.java:

    private void write(String s) {
        try {
            synchronized (this) {
                ensureOpen();
                textOut.write(s);
                textOut.flushBuffer();
                charOut.flushBuffer();
                if (autoFlush && (s.indexOf('\n') >= 0))
                    out.flush();
            }
        }
        catch (InterruptedIOException x) {
            Thread.currentThread().interrupt();
        }
        catch (IOException x) {
            trouble = true;
        }
    }
    

    textOut : it is a BufferedWriter object, writing not only character arrays but also strings and text.
    charOut : it is a OutputStreamWriter object, writing character arrays into a stream.

    So PrintStream.write() calls BufferedWriter.write() and flushes both textOut(BufferedWriter) and charOut(OutputStreamWriter) buffers.

    The above information is enough. There is no need to go deep down as there are many levels still left .There is a call of write() method only by various streams at each further level.Ultimately, after many write() calls the stream is attached to the standard input/output.

    System.out.println vs loggers like Log4j


    Log4J has mulitple 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.

    How system.out.println works in java

    System.err and System.in


    Let's talk about the remaining two static variable in System class '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 output 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?");
    }
    }
    }
    


    Change "out" of System.out.println and Redirect it to Text file


    'out' object can be customized. At startup out gets initialized by java runtime environment and it can be changed by the 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) {}
       }
    }
    


    Please mention in the comments if you have any questions or queries.



    About The Author

    Subham Mittal has worked in Oracle for 3 years .
    For more java articles ,Click here to Subscribe JavaHungry