考虑以下简化的测试用例:
import java.util.AbstractList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.function.BiFunction;
import java.util.function.Function;
public final class Example {
static class PairList<A, B> {
public void replaceAllSecond(Function<? super B, ? extends B> secondFunction) {}
public void replaceAllSecond(BiFunction<? super A, ? super B, ? extends B> secondFunction) {}
}
static class ImmutableList<E> extends AbstractList<E> {
public static <E> ImmutableList<E> copyOf(Iterable<? extends E> elements) {return null;}
public static <E> ImmutableList<E> copyOf(Collection<? extends E> elements) {return null;}
public static <E> ImmutableList<E> copyOf(Iterator<? extends E> elements) {return null;}
public static <E> ImmutableList<E> copyOf(E[] elements) {return null;}
@Override public E get(int index) {return null;}
@Override public int size() {return 0;}
}
public static void foo() {
PairList<Integer, List<Integer>> list = new PairList<>();
list.replaceAllSecond(x -> ImmutableList.copyOf(x)); //accepted
list.replaceAllSecond(ImmutableList::copyOf); //error
}
}
用javac从oraclejdk8u40编译,调用 replaceAllSecond
接受lambda,但传递方法引用的调用被拒绝,并出现以下错误:
Example.java:26: error: reference to replaceAllSecond is ambiguous
list.replaceAllSecond(ImmutableList::copyOf); //error
^
both method replaceAllSecond(Function<? super B,? extends B>) in PairList and method replaceAllSecond(BiFunction<? super A,? super B,? extends B>) in PairList match
where B,A are type-variables:
B extends Object declared in class PairList
A extends Object declared in class PairList
1 error
我不明白为什么超载 BiFunction
可能适用于这里。根据jls 15.12.2.1(省略部分项目符号):
当且仅当以下所有条件均为真时,成员方法才可能适用于方法调用:
如果成员是arity为n的固定arity方法,则方法调用的arity等于n,对于所有i(1≤ 我≤ n) ,方法调用的第i个参数可能与方法的第i个参数的类型兼容,如下所述。
根据以下规则,表达式可能与目标类型兼容:
方法引用表达式(§15.13)与函数接口类型潜在兼容,如果该类型的函数类型arity为n,则至少存在一个arity为n的方法引用表达式的潜在适用方法(§15.13.1),且下列情况之一成立:
方法引用表达式的格式为referencetype::[typearguments]identifier,并且至少有一个可能适用的方法i)static并支持arity n,或者ii)not static并支持arity n-1。
在我看来, BiFunction
的函数类型arity为2,但的所有重载 copyOf
是静态的并且具有arity 1,因此方法引用可能与 BiFunction
参数等 replaceAllSecond(BiFunction)
可能不适用。
我是误解了jls,还是这是javac错误?jdk-8026231描述了更新javac以实现该规范,但是该错误在2013年得到解决,在java8的第一个版本发布之前(2014年3月)。
1条答案
按热度按时间yfwxisqw1#
您的示例可以进一步简化为以下内容:
我认为这是一个javac问题,因为这段代码在java-9早期的access构建(甚至像9ea57这样非常老的构建)中编译得很好,而在java-8中编译失败(即使是最新的更新)。