代码之家  ›  专栏  ›  技术社区  ›  Jens

使用方法引用和基元类型的函数接口专门化进行重载解析

  •  6
  • Jens  · 技术社区  · 7 年前

    假设我们有一个类和一个重载函数:

    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中遗漏的一点。

    1 回复  |  直到 7 年前
        1
  •  3
  •   Anton    7 年前

    事实并非如此; double int .

    Paragraph 4.10 :

    及物的 关闭 S >₁ T ,即 S :> T 到 指示超类型关系在 S T .

    Paragraph 4.10.1

    以下规则定义了

    double >₁ float

    float >₁ long

    long >₁ int

    这个 超类型 直接超型 关系是指从 (double >₁ float) ∧ (float >₁ long) ∧ (long >₁ int) 跟随 double :> int