– Cześć, Amigo! Dziś nauczysz się, jak zrobić coś nowego: zastąpić obiekt System.out.
System.out jest statyczną zmienną PrintStream o nazwie out w klasie System. Zmienna ta posiada modyfikator final, więc po prostu przypisujesz jej nową wartość. Klasa System ma jednak specjalną metodę, która do tego służy: setOut(PrintStream stream). I to właśnie z niej skorzystamy.

– Interesujące. I czym to zastąpimy?

– Potrzebujemy jakiegoś obiektu, który będzie mógł zbierać dane wyjściowe. ByteArrayOutputStream najlepiej się do tego nadaje. Jest to specjalna klasa, która jest dynamiczną (mającą zmienną wielkość) tablicą i implementuje interfejs OutputStream.

– Adapter pomiędzy tablicą a OutputStream?

– Coś w tym stylu. Oto, jak wygląda nasz kod.

Kod
public static void main(String[] args) throws Exception
{
 //Zapisz bieżący PrintStream w specjalnej zmiennej
 PrintStream consoleStream = System.out;

 //Utwórz dynamiczną tablicę
 ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
 //Utwórz adapter dla klasy PrintStream
 PrintStream stream = new PrintStream(outputStream);
 //Ustaw go jako bieżący System.out
 System.setOut(stream);

 //Wywołaj funkcję, która nie wie nic o naszych zmianach
 printSomething();

 //Konwertuj dane zapisane w naszym ByteArray na ciąg
 String result = outputStream.toString();

 //Przywróć wszystko do poprzedniego stanu
 System.setOut(consoleStream);
}

public static void printSomething()
{
 System.out.println("Cześć");
 System.out.println("Mam na imię Amigo");
 System.out.println("Pa, pa!");
}

– A co zrobimy z tą linią?

– Cóż, cokolwiek chcemy. Na przykład, odwrócimy ją. Wtedy kod wyglądałby tak:

Kod
public static void main(String[] args) throws Exception
{
 //Zapisz bieżący PrintStream w specjalnej zmiennej
 PrintStream consoleStream = System.out;

 //Utwórz dynamiczną tablicę
 ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
 //Utwórz adapter dla klasy PrintStream
 PrintStream stream = new PrintStream(outputStream);
 //Ustaw go jako bieżący System.out
 System.setOut(stream);

 //Wywołaj funkcję, która nie wie nic o naszych zmianach
 printSomething();

 //Konwertuj dane zapisane w naszym ByteArray na ciąg
 String result = outputStream.toString();

 //Przywróć wszystko do poprzedniego stanu
 System.setOut(consoleStream);

 //Odwróć ciąg
 StringBuilder stringBuilder = new StringBuilder(result);
 stringBuilder.reverse();
 String reverseString = stringBuilder.toString();

 //Wypisz go do konsoli
 System.out.println(reverseString);
}

public static void printSomething()
{
 System.out.println("Cześć");
 System.out.println("Mam na imię Amigo");
 System.out.println("Pa, pa!");
}

– Ciekawe! Teraz zaczynam rozumieć, jak wielkie możliwości dają te małe klasy.
– Dziękuję za interesującą lekcję, Bilaabo.