将一种方法标记为首选以自动解决模糊调用?

时间:2014-06-30 01:15:30

标签: java ambiguous-call

让我们说我自己定义了一种新类型的字节流(类似于OutputStream):

public interface MyByteStream {
    public void write(byte[] data) throws IOException;
}

另外,我有一个可以将字符串写入字节流的辅助类,为了灵活性,我希望它的方法有两个版本,以便它可以使用常规的OutputStream或我的新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());
    }
}

现在,如果我有一个扩展OutputStream的类实现MyByteStream,就像这样:

public class DebugStream extends OutputStream implements MyByteStream {
    @Override
    public void write(int b) throws IOException {
        System.out.println(b);
    }
}

我不能像这样调用我的StringWriter写法:

new StringWriter().write("Hello", new DebugStream());

因为它会给我以下错误:

The method write(String, MyByteStream) is ambiguous for the type StringWriter

我可以通过将DebugStream显式地转换为其中一个字节流来解决问题,如下所示:

new StringWriter().write("Hello", (OutputStream) new DebugStream());
new StringWriter().write("Hello", (MyByteStream) new DebugStream());

但是既然这两种方法完全相同,我宁愿不必在任何地方进行演员表演。这有什么办法吗?比如将这些方法中的一个定义为这种模糊调用的首选方法?或者也许是一些仿制药?

注意:

我想保持编译时类型安全性,所以"解决方案"沿着以下几行:

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

1 个答案:

答案 0 :(得分:1)

有两个主要选项:

1)以不同方式命名方法,而不是重载现有方法:

public void write(String string, OutputStream stream) {
    //
}

public void writeMyByteStream(String string, MyByteStream stream) {
    //
}

这不是一个好的解决方案,因为它会污染API并带有实现细节,但它是一个选项。

2)使用一个公共方法,但私下选择如何处理流类型:

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) {
    //
}

更清洁的方式是第二个,因为API更简单,客户不需要知道该类对MyByteStream执行任何特殊操作。这也意味着可以在不改变任何客户端代码的情况下从实现中撤回特殊支持。

有些人可能会质疑从样式角度使用instanceof,但是当你需要它时,你需要它。