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.
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.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()
public void print(String s) {
if (s == null) {
s = "null";
}
write(s);
}
Going one more level and looking at write():
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.
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.