假设我们有一个类和一个重载函数:
public class Main {
static final class A {
}
public static String g(ToIntFunction<? extends A> f) {
return null;
}
public static String g(ToDoubleFunction<? extends A> f) {
return null;
}
}
public class Main {
static final class A {
}
public static String g(ToIntFunction<? extends A> f) {
return null;
}
public static String g(ToDoubleFunction<? extends A> f) {
return null;
}
private static int toInt(A x) {
return 2;
}
public static void main(String[] args) {
ToIntFunction<? extends A> f1 = Main::toInt;
ToDoubleFunction<? extends A> f2 = Main::toInt;
g(Main::toInt);
}
}
这适用于javac,但不适用于eclipse ecj。我向ecj提交了一份错误报告,但我不确定这是ecj还是javac错误,并试图遵循过载解决算法来解决它。我的感觉是代码应该被接受,因为从直觉上看,这是合理的
ToIntFunction
更适合
toInt
ToDoubleFunction
我必须承认,我对JLS规范有点迷茫,希望能得到一些帮助。我首先想计算
Main::double2int
,所以我看了看
15.13.2. Type of a Method Reference
. 它不定义类型,但定义了类型在不同上下文中何时兼容:
方法引用表达式在赋值上下文中兼容,
功能接口类型(§9.8),表达式与
从T。
接地类型为
ToIntFunction<A>
和
ToDoubleFunction<A>
托因
返回一个与double赋值兼容的int,因此我可以得出结论,方法引用与
ToIntFunction<? extends A>
和
ToDoubleFunction<? extends A>
ToIntFunction<?扩展A>
和
这在主功能中是可以接受的。
然后我看了一下过载分辨率,发现
15.12.2.5. Choosing the Most Specific Method
或
对于参数更具体
Main::toInt
A -> int
如果T不是S的子类型,并且以下情况之一为真(其中U1…Uk和R1是S的捕捉的函数类型的参数类型和返回类型,V1…Vk和R2是T的函数类型的参数类型和返回类型),则函数接口类型S比表达式e的函数接口类型T更具体:
是真的:
R2无效。
R1<:R2。
R1是基元类型,R2是引用类型,编译时
方法引用的声明的返回类型为
基元类型。
R1是引用类型,R2是基元类型,编译时
参考类型。
两个接口
ToIntFunction
ToDouble函数
只在返回类型(基元类型)上有所不同
double
和
int
. 对于基本类型,4.10.1中根据类型的大小定义了子句“R1<:R2”。两者之间没有关系
,因此本例没有定义哪种类型更具体。
最后两点也不适合,因为这两个函数接口都没有引用类型的返回值。
当两个函数接口返回原语,并且代码因不明确而被拒绝时,似乎没有规则。然而,javac接受了代码,我希望它也能接受。所以我想知道这是否是JLS中遗漏的一点。