8.1 Replacing System.out

Typically, an application generates output to System.out or System.err, if only for logging purposes during development. It is important to realize that this output can affect performance. Any output not present in the final deployed version of the application should be turned off during performance tests; otherwise, your performance results can get skewed. This is also true for any other I/O: to disk, pipes, other processes, or the network.

It is best to include a framework for logging output in your design. You want a framework that centralizes all your logging operations and lets you enable or disable certain logging features (perhaps by setting a "debug level"). You may want to implement your own logging class, which decides whether to send output at all and where to send it. The Unix syslog utility provides a good starting point for designing such a framework. It has levels of priority (emergency, alert, critical, error, warning, notice, info, debug) and other aspects that are useful to note. SDK 1.4 introduced a logging API, the java.util.logging package. This includes logging levels and output redirection, as I show briefly in the next section.

If you are already well into development without this kind of framework but need a quick fix for handling unnecessary output, it is still possible to replace System.out and System.err.

It is simple to replace the print stream in System.out and System.err. You need an instance of a java.io.PrintStream or one of its subclasses, and you can use the System.setOut( ) and System.setErr( ) methods to replace the current PrintStream instances. It is useful to retain a reference to the original print-stream objects you are replacing, since these retain access to the console. For example, the following class simply eliminates all output sent to System.out and System.err if TUNING is true; otherwise, it sends all output to the original destination. This class illustrates how to implement your own redirection classes:

package tuning.console;
public class PrintWrapper
  extends java.io.PrintStream
  java.io.PrintStream wrappedOut;
  public static boolean TUNING = false;
  public static void install(  )
    System.setOut(new PrintWrapper(System.out));
    System.setErr(new PrintWrapper(System.err));
  public PrintWrapper(java.io.PrintStream out)
    wrappedOut = out;
  public boolean checkError(  ) {return wrappedOut.checkError(  );}
  public void close(  ) {wrappedOut.close(  );}
  public void flush(  ) {wrappedOut.flush(  );}
  public void print(boolean x) {if (!TUNING) wrappedOut.print(x);}
  public void print(char x) {if (!TUNING) wrappedOut.print(x);}
  public void print(char[  ] x) {if (!TUNING) wrappedOut.print(x);}
  public void print(double x) {if (!TUNING) wrappedOut.print(x);}
  public void print(float x) {if (!TUNING) wrappedOut.print(x);}
  public void print(int x) {if (!TUNING) wrappedOut.print(x);}
  public void print(long x) {if (!TUNING) wrappedOut.print(x);}
  public void print(Object x) {if (!TUNING) wrappedOut.print(x);}
  public void print(String x) {if (!TUNING) wrappedOut.print(x);}
  public void println(  ) {if (!TUNING) wrappedOut.println(  );}
  public void println(boolean x) {if (!TUNING) wrappedOut.println(x);}
  public void println(char x) {if (!TUNING) wrappedOut.println(x);}
  public void println(char[  ] x) {if (!TUNING) wrappedOut.println(x);}
  public void println(double x) {if (!TUNING) wrappedOut.println(x);}
  public void println(float x) {if (!TUNING) wrappedOut.println(x);}
  public void println(int x) {if (!TUNING) wrappedOut.println(x);}
  public void println(long x) {if (!TUNING) wrappedOut.println(x);}
  public void println(Object x) {if (!TUNING) wrappedOut.println(x);}
  public void println(String x) {if (!TUNING) wrappedOut.println(x);}
  public void write(byte[  ] x, int y, int z) {
    if (!TUNING) wrappedOut.write(x,y,z);}
  public void write(int  x) {if (!TUNING) wrappedOut.write(x);}