为什么这个方法有歧义?



我有两个多态方法,采用两种类型的类作为输入。

我希望基于对象的流执行两个不同的操作。

相反,他告诉我这个方法有歧义。

不使用流显然可以工作。我的目的是使用它们。

怎么解?

帮帮我,我不明白。谢谢。
Stream.of(1,"Text").forEach(Test::method);

static void method(Integer i){
System.out.println("i");
}
static void method(String i){
System.out.println("s");
}

如果你将流赋值给一个局部变量,你会看到Stream.of(1,"Text")的类型是Stream<Object>

Stream<Object> x = Stream.of(1,"Text");

因此forEach所需的方法类型是:

static void method(Object obj){
System.out.println("Object is: "+obj);
}

如果您使用了Stream.of(1,2)Stream.of("Hello", "Text"),那么方法调用将按照您的预期进行解析。

您可以添加一个接受Object参数的方法,并使用这种方法:

import java.util.stream.Stream;
public class Test {
static void method(Object o) {
if(o instanceof String)
method((String)o);
if(o instanceof Integer)
method((Integer)o);
}
static void method(Integer i) {
System.out.println("i");
}
static void method(String i) {
System.out.println("s");
}
public static void main(String[] args) {
Stream.of(1, "Text").forEach(element -> {
Test.method( element );
});
}
}

Java只在编译时解析重载。当迭代1时,您似乎希望Test::method解析为method(Integer)(第一次重载),并在迭代"Text"时解析为method(String)(第二次重载)。这是不可能的,Test::method只能解析一件事。

错误信息确实有点令人困惑。问题不在于这两种方法之间存在歧义。问题是,由于流中既有字符串又有整数,forEach希望您为它提供一个方法,该方法可以接受字符串和整数(或者更准确地说,是StringInteger之间的通用超类型,因为Java中没有联合类型)。

static void method(Object o){
}

但是method的两个重载都不能同时接受字符串和整数。

要做你想做的,你必须在运行时检查类型,并手动调用重载:

Stream.of(1,"Text").forEach(x -> {
if (x instanceof Integer) {
method((Integer)x);
} else if (x instanceof String) {
method((String)x);
}
});

我建议你不要将字符串和整数放在同一个流中。

如果涉及的类型不是StringInteger,而是您编写的类,情况将不同。因为这样您就可以将method编写为公共超类中的实例方法。与重载解析不同,选择运行的实例方法的覆盖实现是在运行时完成的。

class Superclass {
public void method() {

}
}
class BaseClass1 extends Superclass {
@Override
public void method() {
System.out.println("i");
}
}
class BaseClass2 extends Superclass {
@Override
public void method() {
System.out.println("s");
}
}
// ...
Stream.of(new BaseClass1(), new BaseClass2()).forEach(Superclass::method);

由于Stream.of(1, "Text", null)中的元素类型是所有三个参数的共同超类型,因此可以实现接受Object类型参数的方法,以将调用分派到适当的重载method(null值也应处理为映射到某些特定的方法):

Stream.of(1,"Text", null).forEach(Test::method);
static void method(Object o) {
if (o instanceof Integer) {
method((Integer) o);
} else if (o instanceof String || null == o) {
method((String) o);
} else {
method(o.toString());
}
}

输出:

i
s
s

关于语句:

不使用流显然可以工作。

这似乎不是真的。

如果一个原始列表/数组被创建并使用,而不是流,也会出现类似的问题:

List list = Arrays.asList(1, "Text", null);
// list.forEach(Test::method); // fails too, same error as below
for (int i = 0; i < list.size(); i++) {
method(list.get(i));
}

在这种情况下,错误看起来像:

/Test.java:10: error: no suitable method found for method(Object)
method(list.get(i));
^
method Test.method(Integer) is not applicable
(argument mismatch; Object cannot be converted to Integer)
method Test.method(String) is not applicable
(argument mismatch; Object cannot be converted to String)
1 error

最新更新