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();
}
}
}