Jen*_*ens 6 java language-lawyer overload-resolution method-reference
假设我们有一个类和一个重载函数:
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;
}
}
Run Code Online (Sandbox Code Playgroud)
我想用方法引用调用g来调用类型为A的函数 - > int:
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);
}
}
Run Code Online (Sandbox Code Playgroud)
这适用于javac,但不适用于eclipse ecj.我向ecj提交了一个错误报告,但我不确定这是否是一个ecj或javac错误,并尝试按照重载解析算法来解决它.我的感觉是,代码应该被接受,因为它是直观合理的ToIntFunction是更好的匹配toInt比ToDoubleFunction.但是,我对JLS的解读是它应该被拒绝,因为没有理由让一个更具体.
我不得不承认我在JLS规范中有点迷失,并会感谢一些帮助.我首先想要计算它的类型Main::double2int,所以我看了15.13.2.方法参考的类型.它没有定义类型,但它定义了何时类型在不同的上下文中兼容:
如果T是函数接口类型(第9.8节),并且表达式与从T派生的地面目标类型的函数类型一致,则方法引用表达式在赋值上下文,调用上下文或具有目标类型T的转换上下文中是兼容的.
地面类型是ToIntFunction<A>和ToDoubleFunction<A>.toInt返回一个int是分配兼容的两倍,所以我可以得出结论,该方法是参考与campatible ToIntFunction<? extends A>和ToDoubleFunction<? extends A>在调用上下文.这可以通过将方法引用到两者ToIntFunction<? extends A>并且ToDoubleFunction<? extends A>在主函数中被接受来验证.
然后我查看了重载决议,找到了15.12.2.5.选择具有方法引用特殊情况的最具体方法,以确定两个重载中的哪一个ToIntFunction或ToDoubleFunction更具体地用于Main::toInt编译时声明的参数A -> int.
如果T不是S的子类型且下列之一为真,则功能接口类型S比表达式e的功能接口类型T更具体(其中U1 ... Uk和R1是参数类型和返回类型捕获S的函数类型,V1 ... Vk和R2是T)函数类型的参数类型和返回类型:
...
如果e是精确的方法参考表达式(§15.13.1),则i)对于所有i(1≤i≤k),Ui与Vi相同,并且ii)以下之一为真:
R2无效.
R1 <:R2.
R1是基本类型,R2是引用类型,方法引用的编译时声明具有返回类型,它是基本类型.
R1是引用类型,R2是基本类型,方法引用的编译时声明具有返回类型,它是引用类型.
第一个条件显然不匹配,因为R1和R2不是空的.
这两个接口ToIntFunction和ToDoubleFunction他们的返回类型,其是原始类型的差异仅在于double和int.对于基本类型,根据类型的大小,在4.10.1中定义子句"R1 <:R2".double和之间没有关系int,因此这种情况不能定义哪种类型更具体.
最后两点不适合,因为两个功能接口都没有引用类型的返回值.
当两个功能接口返回原语并且代码应该被拒绝为模糊时,似乎没有规则.但是,javac接受了代码,我希望它能够这样做.所以我想知道这是否是JLS中的缺失点.
\n\n\n对于原始类型,根据类型的大小,在 4.10.1 中定义了子句“R1 <: R2”。double 和 int 之间没有关系,因此本例没有定义哪种类型更具体。
\n
不是这种情况; double事实上,是一个超类型int。
\n\n\n\n\n类型的超类型是通过直接超类型关系(写作 )上的自反和传递闭包
\nS >\xe2\x82\x81 T获得的,该关系由本节后面给出的规则定义。我们写到S :> T\n表示父类型关系在S和 之间成立T。
\n\n\n以下规则定义了原始类型之间的直接父类型关系:
\n\n\n\n
double >\xe2\x82\x81 float\n\n
float >\xe2\x82\x81 long\n
long >\xe2\x82\x81 int
超类型关系是直接超类型关系的自反和传递闭包,意味着 from(double >\xe2\x82\x81 float) \xe2\x88\xa7 (float >\xe2\x82\x81 long) \xe2\x88\xa7 (long >\xe2\x82\x81 int)如下double :> int。
| 归档时间: |
|
| 查看次数: |
175 次 |
| 最近记录: |