CodeGym /Courses /Java Core /Let's write our own wrapper for System.out

Let's write our own wrapper for System.out

Java Core
Level 9 , Lesson 7
Available

"Hello, Amigo! Today you're going to learn how to do something new: replace the System.out object."
System.out is a static PrintStream variable called out in the System class. This variable has the final modifier, so you simply assign it a new value. However, the System class has a special method to do this: setOut(PrintStream stream). And that's what we'll use.

"Interesting. And what will we replace it with?"

"We need some object that can collect the output data. ByteArrayOutputStream is best suited for this job. This is a special class that is a dynamic (resizable) array and implements the OutputStream interface."

"An adapter between an array and OutputStream?"

"Something like that. Here's what our code looks like."

Code
public static void main(String[] args) throws Exception
{
 //Save the current PrintStream in a special variable
 PrintStream consoleStream = System.out;

 //Create a dynamic array
 ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
 //Create an adapter for the PrintStream class
 PrintStream stream = new PrintStream(outputStream);
 //Set it as the current System.out
 System.setOut(stream);

 //Call a function that knows nothing about our changes
 printSomething();

 //Convert the data written to our ByteArray into a string
 String result = outputStream.toString();

 //Put everything back to the way it was
 System.setOut(consoleStream);
}

public static void printSomething()
{
 System.out.println("Hi");
 System.out.println("My name is Amigo");
 System.out.println("Bye-bye!");
}

"And what will we do with this line?"

"Well, whatever we want. For example, we would reverse it. Then the code would look like this:"

Code
public static void main(String[] args) throws Exception
{
 //Save the current PrintStream in a special variable
 PrintStream consoleStream = System.out;

 //Create a dynamic array
 ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
 //Create an adapter for the PrintStream class
 PrintStream stream = new PrintStream(outputStream);
 //Set it as the current System.out
 System.setOut(stream);

 //Call a function that knows nothing about our changes
 printSomething();

 //Convert the data written to our ByteArray into a string
 String result = outputStream.toString();

 //Put everything back to the way it was
 System.setOut(consoleStream);

 //Reverse the string
 StringBuilder stringBuilder = new StringBuilder(result);
 stringBuilder.reverse();
 String reverseString = stringBuilder.toString();

 //Output it to the console
 System.out.println(reverseString);
}

public static void printSomething()
{
 System.out.println("Hi");
 System.out.println("My name is Amigo");
 System.out.println("Bye-bye!");
}

"How interesting! Now I'm beginning to understand a little bit of the great capabilities these small classes provide."
"Thank you for the interesting lesson, Bilaabo."

Comments (25)
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION
Dyrits Level 1
13 October 2020
"And what will we do with this line?" "Well, whatever we want. For example, we would reverse it. Then the code would look like this:" That's a stupid example... So, I repeat the question... "And what will we do with this line?"
Aldo Luna Bueno Level 1, Peru
30 March 2022
I think it could be used to intercept what another programmer's method would print to the console. Maybe we don't want any message to be printed or we want to make changes to it.
Thomas Level 41, Bayreuth, Germany
23 May 2020
This variable has the final modifier, so you simply assign it a new value. this should be This variable has the final modifier, so you can not simply assign it a new value.
matemate123 Level 50, Kraków, Poland
30 January 2023
I think 2023 it's time to repair this mistake.
Олег Байбула Level 32, Ukraine Expert
3 March 2023
It won't help.
Abdul Alhazred Level 33, Minsk, Belarus
29 September 2024
2024?
Rene Level 28, Netherlands
16 October 2024
Yes, 2024 is still do-able.
fzw Level 41, West University Place, United States
13 April 2020
PrintStream looks more like a decorator for OutputStream to me instead of an adapter
Robert Constantinescu Level 25, Bucharest, Romania
1 February 2020
I think the whole idea here is that: after doing these

System.setOut(stream);
- Using the System.out.println() method, now it writes the strings to the ByteArrayOutputStream, instead of printing them out to the console. So calling the method

printSomething();
System.out.println() write the strings into the ByteArrayOutputStream, instead of printing them to the console - Then what you wrote in the ByteArrayOutputStream, you save it to a string (result) and use the StringBuilder to reverse the content from the ByteArrayOutputStream. - so you saved the content of ByteArrayOutputStream into the result variable and after doing these

System.setOut(consoleStream);
- you set the System.out.println() method to print again to the console instead of "printing"(writing) to the ByteArrayOutputStream Note: The reverse method can be use on any string. Try it for yourself

 StringBuilder stringBuilder = new StringBuilder("you can literally put here any string");
 stringBuilder.reverse();
 String reverseString = stringBuilder.toString();
System.out.println(reverseString);
SOUFIANE DAHIMI Level 32, Marrakech, Morocco
5 January 2020
the printStream class : is it an adapter or a wrapper ???!!!
Johannes Level 27, Centurion, Pretoria, South-Africa
17 April 2020
unfortunately I don't understand the difference. Still too early in JAVA for me :)
SOUFIANE DAHIMI Level 32, Marrakech, Morocco
17 April 2020
I did some research and I found that there aren't t the same. Wrapper = design pattern that allow you to add new functionalities to the interface. Adapter = design pattern that allow you to adapt an interface so that it would work with another class that expect another interface.
Andrei Level 41
5 February 2021
So what stops you from adding new functionalities to the interface to act as an adapter? Aren't they the same thing?
Wei Cui Level 39, Newark, United States
6 November 2019
This example help me easier understand how this work; one output stream is console

PrintSteam out = System.out;
one output stream to a file

PrintStream ps = new PrintStream("C:\\Documents and Settings\\Administrator\\Desktop\\log.txt");
set current output stream to file

System.setOut(ps);
write to file

System.out.println("hello world");
set output stream back to console

System.setOut(out);
display output stream on console

System.out.println("back on console");
Ahmed Level 23, Amsterdam, Netherlands
8 December 2019
Now i understand it! Thanks! 😊
Robert Constantinescu Level 25, Bucharest, Romania
24 December 2019
oh, now it makes more sense why i would use it. Thanks !
30 April 2020
This is the best explanation for streams in Level 9.8 :) !
Gellert Varga Level 23, Szekesfehervar, Hungary
21 September 2021
This is a very good and expressive example, thank you Wei Cui!
Ewerton Level 30, Belo Horizonte, Brasil
5 July 2019
Nope, didn't understand that, but practice makes perfect, so... let's keep going.
Ewerton Level 30, Belo Horizonte, Brasil
5 July 2019
Okay, so here it is what I discovered: On line 4, we are just creating a backup, because we will modify the println method.
PrintStream backup = System.out;
Here, we are creating the variable who will store our println.
ByteArrayOutputStream storage = new ByteArrayOutputStream();
So, we tell Java how to do this.

 PrintStream newPrint = new PrintStream(storage);
 System.setOut(newPrint);
Then, you just needs to change what you want with storage, then restore to default with:

System.setOut(backup);
And then print your modification of storage, e.g. , a string, an int, nothing, whatever.

System.out.println(thingWeDidWithStorage);
Yu-Ping Lin Level 29
8 September 2019
printSomething() after System.setOut(newPrint) but before System.setOut(backup) is important. It is the true printout function has been called. Without this line, it won't print out anything when System.out.println(thingWeDidWithStorage) trigger the print function.
Jason Level 26, Rancho Cucamonga, United States
18 October 2019
I do appreciate that explanation and it has brought me closer to clarity but I still don't understand why the backup need to be brought back before you can use any of this or even what the hell the logical path is behind all this. really wish there was like a workflow diagram to look at for this or whatever it may be called. feel like that would really be extremely useful here.
Juanf Level 26
21 October 2019
You backup the System.out into consoleStream just in case later on you want to print something to the console. It's just that: If you don't save at the beginning your original configuration of System.out, then afterwards you won't be able to set again System to print on the console, so System.out will be always printing to the ByteArrayOutputStream you set (or to new ones, if you want to, but you won't be able to set it again to print into the console).
Robert Constantinescu Level 25, Bucharest, Romania
8 December 2019
I've also did not get it. It looks like the whole point of this is to use something else to print to the console, but if we comment

        //Put everything back to the way it was
        System.setOut(consoleStream);
this, nothing will be printed to the console, so i don't really get what is the whole point of changing the System.out in the beginning.
Fadi Alsaidi Level 34, Carrollton, TX, USA
7 April 2020
Just to add to to what has already been explained and to emphasis why we a create a backup. "out" is a variable in the System class and just like any variable you can overwrite it and once you do you would lose it's older value. This example doesn't show what this "out" variable is currently referencing and the example just simply created another variable that reference the same object as the variable "out". That might be a lazy easy way to do this instead of finding out what "out" used to reference and simply System.setOut() again to the same object its was referencing .and now I need to know lol...dammmn it