I'd like to write Java code (say, a method) that will print some lines.
The object onto which to print shall be provided by the caller. I'd like my code to not care what exactly that object is and simply call that objects' println() or println(String) methods. It should work whether that object is a java.io.PrintStream (e.g. System.out) or a java.io.PrintWriter (e.g. constructed by the caller with new PrintWriter(System.out) or new PrintWriter(new ByteArrayOutputStream())).
This would be easy if the potential classes of a "printlineable" object would share some interface that mandated the println() and println(String) methods. However they don't.
So what do I put into the signature to receive such an object without violating the DRY principle by writing twice what is essentially the same implementation, just with swapped out types (as I would have to when simply overloading the function)?
public void sayHello( ??? outThingy) {
outThingy.println("Hello World");
outThingy.println();
// This just a minimal example.
// The real implementation might be more involved
// and non-trivial, so that avoiding duplication
// becomes a real concern.
};
// sayHello should be usable like this:
sayHello(System.out);
// but also like this:
baos = new ByteArrayOutputStream();
pw = new PrintWriter(baos)
sayHello(pw);
pw.flush();
System.out.println(baos.toString());
Or should the fact that PrintStream and PrintWriter don't share such an interface be treated as indication that they aren't interchangeable in the regard of providing a way to print lines? (Rather than that being some kind of historical oversight back when these classes were specified.)
The easiest way would just to overload the method with a version that accepts a PrintWriter and a version that accepts a PrintStream:
public void sayHello(PrintStream outThingy) {
outThingy.println("Hello World");
outThingy.println();
};
public void sayHello(PrintWriter outThingy) {
outThingy.println("Hello World");
outThingy.println();
};
Here's a way you could do it and at least keep the client of the outThingy DRY. But, you'll make a trade off for effectively having a couple WET classes. Still, the amount of code is minimal.
// Printer allows for a common interface
interface Printer {
void println(String line);
void println();
}
// Used with PrintStream
class StreamPrinter implements Printer {
private PrintStream ps;
public StreamPrinter(PrintStream ps) {
this.ps = ps;
}
#Override
public void println(String line) {
ps.println(line);
}
#Override
public void println() {
ps.println();
}
}
// Used with PrintWriter
class TypeWriter implements Printer {
private PrintWriter pw;
public TypeWriter(PrintWriter pw) {
this.pw = pw;
}
#Override
public void println(String line) {
pw.println(line);
}
#Override
public void println() {
pw.println();
}
}
class Talker {
// This class doesn't care!
void sayHello(Printer printer) {
printer.println("Hello world");
printer.println();
}
}
You might be interested in a different, more functional approach. Instead of worrying about what each type offers and how to find a common interface between them, you can achieve the same thing with less code by using a Consumer and a Runnable as representations of the println methods.
// This is the common class
class FuncPrinter {
private Consumer<String> consumer;
private Runnable runnable;
public FuncPrinter(PrintWriter writer) {
consumer = writer::println;
runnable = writer::println;
}
public FuncPrinter(PrintStream stream) {
consumer = stream::println;
runnable = stream::println;
}
public void println(String line) {
consumer.accept(line);
}
public void println() {
runnable.run();
}
}
class Talker {
void sayHello(FuncPrinter fp) {
fp.println("Hello World");
fp.println();
}
}
And you could use it like so:
Talker t = new Talker();
FuncPrinter fp = new FuncPrinter(System.out);
t.sayHello(fp);
ByteArrayOutputStream ostream = new ByteArrayOutputStream();
PrintWriter pw = new PrintWriter(ostream);
fp = new FuncPrinter(pw);
t.sayHello(fp);
fp = new FuncPrinter(
line -> System.out.println(line),
() -> System.out.println(42));
t.sayHello(fp);
Related
I am building a simple logger class-
public class MyLogger {
private final PrintWriter errorWriter;
public MyLogger(OutputStream outputStream) {
final Writer errorStreamWriter = new OutputStreamWriter(outputStream);
this.errorWriter = new PrintWriter(errorStreamWriter);
}
public void start() {
errorWriter.flush();
}
public void addError(String errorMessage) {
errorWriter.println(errorMessage);
}
public void finish() {
errorWriter.flush();
errorWriter.close();
}
}
Now I want to write a unit test to test whether the streams are getting flushed or not, in short if we comment the following methods-
public void start() {
// errorWriter.flush();
}
public void finish() {
// errorWriter.flush();
// errorWriter.close();
}
then the test should fail, I do not wish to use reflection even if it provides a solution, I feel that this isn't possible as we have no control over the errorWriter and other connected streams won't be flushed when the chained stream is flushed, but still, if there is a solution, kindly let me know.
There are some possiblities how you can test this. I am using Mockito as mocking framework in the examples.
I would prefer solution 1) all other are more or less hacks, but the pattern can be useful for more dificult classes which use database connections or other expensive objects.
You test against the public API of you class(like a black box). The caller did not know anything about the internal PrintWriter and has no need to know anything about it.
However you can write a test to ensure the OutputStream is flushed since this is propagated (at least with standard Java Streams). This would fail if you comment out the flush in the start method.
class MyLoggerTest {
OutputStream out = mock(OutputStream.class);
MyLogger myLogger = new MyLogger(out);
#Test
void should_call_flush_out_stream() throws IOException {
myLogger.start();
verify(out).flush();
}
}
You change your class to have a second protected constructor which accepts a PrintWriter. The public constructor uses this one and you use a mock and the second constructor in your test for the flush. The test is similar to the one in 1) but you use a mock(printWriter.class).
public class MyLogger {
private final PrintWriter errorWriter;
public MyLogger(OutputStream outputStream) {
this(new PrintWriter(new OutputStreamWriter(outputStream)));
}
MyLogger(PrintWriter writer) {
this.errorWriter = writer;
}
....
You did not access the PrintWriter directly from the member variable, but create an internal getter method, which can then be used in a Spy to change the internal representation.
public class MyLogger {
private final PrintWriter errorWriter;
...Constructor...
PrintWriter getWriter() {
return errorWriter;
}
public void start() {
getWriter().flush();
}
...
}
And the test would look like this:
class MyLoggerTest {
OutputStream out = mock(OutputStream.class);
PrintWriter writer = mock(PrintWriter.class);
MyLogger myLogger = spy(new MyLogger(out));
#BeforeEach
void setup() {
when(myLogger.getWriter()).thenReturn(writer);
}
#Test
void should_call_flush_out_stream() {
myLogger.start();
verify(writer).flush();
}
}
I'm calling the main method of a class via reflection. For example:
Object o = clasz.getDeclaredConstructor().newInstance();
Method method = clasz.getMethod("main", String[].class);
method.invoke(o, new String[1]);
The called code looks as:
public class Test {
public static void main(String[] args) {
System.out.println("This is a test");
}
}
The reflection works fine and I can see the message in the console.
Is there a way to register something like a binding to the method invocation, for example a PrintWriter or a custom decorated Writer, so I can get the print value as a String?
You can change what System.out is bound to using System.setOut();. You can then make your own:
public class MyTeeingPrinter extends OutputStream {
private final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
private final PrintStream original;
public MyTeeingPrinter(PrintStream original) {
this.original = original;
}
#Override public void write(int b) {
original.write(b);
buffer.write(b);
}
public String getAndClear() {
String s = buffer.toString(StandardCharsets.UTF_8);
buffer.reset();
return s;
}
}
And then:
MyTeeingPrinter tee = new MyTeeingPrinter();
System.setOut(new PrintStream(tee));
and now you can invoke tee.getAndClear().
It's a bit of a slog, because whatever code you are running like this is presumably badly designed - it should have instead taken a PrintStream or preferrably an Appendable or Writer, and would write into this writer. Then a trivial one-liner main can be made that just tosses System.out into a writer and hands that to this code you're attempting to run for the case where you just want that code to run and write to sysout, and you can make your own (and stop using reflecting to invoke that main method) and hand that to this code you are running in this scenario.
Note that your reflective code 'works' but is bizarre. There is no need to make a new instance; main is static. The right way is:
Method method = clasz.getMethod("main", String[].class);
method.invoke(null, new String[1]);
That main() method is called in the same process, hence, you can just provide your own stdout implementation/decorator via java.lang.System.setOut(PrintStream) before the reflection magic
An empty string array would work: new String[1] -> new String[0]
You don't need to create a new object to call the static method. Even though java allows calling static methods via objects, this is a bad style and sometimes might cause problems because of name shadowing. Consider the example below:
public class Parent {
public static void main(String[] args) {
Parent child = new Child();
child.test();
}
public static void test() {
System.out.println("Parent.test()");
}
}
class Child extends Parent {
public static void test() {
System.out.println("Child.test()");
}
}
It actually calls Parent.test() even though it's invoked on a Child object
Sorry I searched a lot but could not find an answer to it. If there is , I a apologize and please let me know.
If I have sent an value via System.out.println or .print is there any way to get it ? I mean after sending get all values sent via System.out and the last sent value ?
System.out.println("Hi");
String val = System.\\something
String last = System.\\something else
Thank you
I guess below code will be useful for you :
Create a class and extend PrintStream
class StorePrintStream extends PrintStream {
public static List<String> printList = new LinkedList<String>();
public StorePrintStream(PrintStream org) {
super(org);
}
#Override
public void println(String line) {
printList.add(line);
super.println(line);
}
public void println(int line) {
this.println(String.valueOf(line));
}
// And so on for double etc..
}
Now use above class to track print information :
public class Test {
public static void main(String[] args) throws Exception {
System.setOut(new StorePrintStream(System.out));
System.out.println("print line");
Test2 t2 = new Test2();
t2.meth1();
System.out.println(StorePrintStream.printList);
}
}
class Test2 {
public void meth1() {
System.out.println("another print");
}
}
There seems to be a bit of a misunderstanding of what System.out.println does. System.out.println sends a String to the Outputstream (stdout) of the Java program. So it is returned to the operation system. That is generally used, to make an output visible to the user, but also to other applications. Another application could read that with System.in.read.
In your case you would like to use the output in the same application, which is unnecessary, because the application knows its own data.
If you need to store a history of the outputted data, you can certainly save the history in you own application - (as suggested in a comment) a decorated PrintStream could do the job.
If you are a Beginner with Java, it might be easier to write a new method that stores your history. Eg. you could add the following to your class:
private static LinkedList<String> stdoutHistory;
public static void betterPrintln(String s)
{
System.out.println(s);
stdoutHistory.add(s);
}
// this method returns the last printed output
public static String getLastOutput()
{
return stdoutHistory.get(stdoutHistory.count()-1);
}
and then call that method, to print something
Let's say I define myself a new type of byte stream (similar to OutputStream):
public interface MyByteStream {
public void write(byte[] data) throws IOException;
}
Also, I have a helper class that can write Strings to a byte stream, and for flexibility, I would like to have two versions of its method, so that it works with either a regular OutputStream or my new MyByteStream:
public class StringWriter {
public void write(String string, MyByteStream stream) throws IOException {
stream.write(string.getBytes());
}
public void write(String string, OutputStream stream) throws IOException {
stream.write(string.getBytes());
}
}
Now, if I have a class that extends OutputStream and implements MyByteStream, like this:
public class DebugStream extends OutputStream implements MyByteStream {
#Override
public void write(int b) throws IOException {
System.out.println(b);
}
}
I can't just call my StringWriter's write method like this:
new StringWriter().write("Hello", new DebugStream());
as it will give me the following error:
The method write(String, MyByteStream) is ambiguous for the type StringWriter
I can resolve the problem by explicitly casting the DebugStream to one of the byte streams, like so:
new StringWriter().write("Hello", (OutputStream) new DebugStream());
new StringWriter().write("Hello", (MyByteStream) new DebugStream());
But since the two methods do the exact same thing anyways, I would much rather not have to do the cast everywhere. Is there some way around this? Like defining one of the methods as preferred for such ambiguous calls? Or maybe some generics-trickery?
Note:
I would like to keep compile-time type-safety alive, so "solutions" along the following lines are out:
public class StringWriter {
public void write(String string, Object stream) throws IOException {
if (stream instanceof OutputStream) {
((OutputStream) stream).write(string.getBytes());
} else if (stream instanceof MyByteStream) {
((MyByteStream) stream).write(string.getBytes());
} else {
throw new IllegalArgumentException();
}
}
}
There are two main options:
1) Name the method differently, rather than overloading the existing one:
public void write(String string, OutputStream stream) {
//
}
public void writeMyByteStream(String string, MyByteStream stream) {
//
}
This is not a good solution, because it pollutes the API with implementation detail, but it's an option.
2) Use one public method, but privately choose how to handle the stream types:
public void write(String string, OutputStream stream) {
if (stream instanceof MyByteStream) {
writeMyByteStream(string, stream);
} else {
writeOutputStream(string, stream);
}
}
private void writeMyByteStream(String string, MyByteStream stream) {
//
}
private void writeOutputStream(String string, OutputStream stream) {
//
}
The cleaner way is this second one, because the API is far simpler and clients don't need to know that the class does any thing special with a MyByteStream. It also means that special support may be withdrawn from the implementation later without changing any client code.
Some may question using instanceof from a style perspective, but when you need it, you need it.
I want a hard reference class in my Java code, but, of course, there isn't one. Is there some other way to do what I want, or should I make my own class?
This comes up with anonymous classes in methods where I want the anonymous class to set the return value for the method.
For example, given
interface Greeting {
void greet();
}
I want code like the following:
// Does not compile
static void hello(final String who) {
String returnValue;
Greeting hello = new Greeting() {
public void greet() {
returnValue = "hello" + who;
}
};
hello.greet();
System.out.println(returnValue);
}
I can fake it using a list:
static void hello(final String who) {
final List<String> returnValue = new ArrayList<String>();
Greeting hello = new Greeting() {
public void greet() {
returnValue.add("hello" + who);
}
};
hello.greet();
System.out.println(returnValue.iterator().next());
}
But I want to not use a list. I can write a StrongReference class that solves this:
static class StrongReference<T> {
private T referent;
public void set(T referent) {
this.referent = referent;
}
public T get() {
return referent;
}
}
which makes my method clearer:
static void hello(final String who) {
final StrongReference<String> returnValue = new StrongReference<String>();
Greeting hello = new Greeting() {
public void greet() {
returnValue.set("hello" + who);
}
};
hello.greet();
System.out.println(returnValue.get());
}
For my contrived example, I could have greet() return a String, but I'm working with much more complex classes, where the setting is deep within a database call that the base class manages. The instances have many different types they want to return, so I've just been using the List trick.
My questions are: Is there a better way to do this? What's wrong with my StrongReference class? Has anyone written a StrongReference in a library somewhere?
If you want something from the standard API, perhaps an AtomicReference would do?
It has void set(V value) and a V get() methods. Unless you have multiple threads involved, just see the synchronization mechanism as a bonus ;-)
A common idiom
final String[] result = { null };
result[0] = ...;
Looks good but I think you should make some kind of synchronization since another thread might set the value.