【问题标题】:What's the type of a method reference? [duplicate]方法引用的类型是什么? [复制]
【发布时间】:2015-12-26 05:30:12
【问题描述】:

说我们有

class A {
   B method1 (C c) { ... }
}

method1 作为方法引用的类型是什么?

这是,这个调用的foo() 的方法签名是什么?:

foo (A::method1);

注意:

我已经定义了一个接口

interface I {
   B m (A a, C c);
}

似乎将 foo 声明为是正确的

void foo (I i) { }

(因为它匹配调用foo(A::method1) --inside foo你必须写b=i.m(a,c)来表示b=a.method1(c))。

这是唯一的出路吗?

【问题讨论】:

    标签: java java-8 method-reference


    【解决方案1】:

    您可以使用现有的BiFunction,而不是声明新接口:

    void foo(BiFunction<? super A, ? super C, ? extends B> fn) {
        ...
        B b = fn.apply(a, c);
        ...
    }
    

    【讨论】:

      【解决方案2】:

      我在这里承认这个问题太复杂了,我无法尝试回答,但我试图理解你的问题,因此提供了我对这种情况的理解 - 你的方法很好。基本上你在这里做以下事情-

      1. 使用简写语法让匿名类实现功能接口 - 这很好。
      2. 让编译器知道使用A::method1 作为I.m 的实现 - 这也很好。
      3. 因为 A::method1 已经存在,您可以使用方法引用而不是 lambda 表达式 - 这也很好。
      4. 实际参数c 的传递在foo 行中的方法体中完成 - b=i.m(a,c)。此处用于c 的实际参数应传递给A::method1
      5. a.method1 中的对象 a 在您指定 Class::Method 而不是 Instance::Method 时保持 任意,根据此语法的 java 8 规范

      【讨论】:

        【解决方案3】:

        非正式解释:

        请记住,可以将方法引用视为某些 lambda 的替代语法,并且 lambda 都实现了一个或多个 functional interfaces

        请记住,lambdas(目前)是一种以更简洁的形式编写一些单方法匿名类的方法;因此,lambdas 总是可以简化为匿名类(但并非总是相反)。

        所以

        foo (A::method1);
        

        可以变成

        foo ((c) -> <body>);
        

        可以简化为匿名类:

        foo (new Function<B>() {
            <body>
        });
        

        这是一个匿名类,是 Function 的子类型

        因此,方法引用是它们所代表的任何功能接口的匿名子类型,因此参数的类型必须是相应的功能接口或其超类型之一。


        JLS 实际上有一个标题为“15.13.2. 方法引用的类型”的部分,但措辞可能有点迟钝。简而言之:

        方法引用可以用作类型T if:

        • T 是功能接口类型(第 9.8 节)
        • 功能接口的抽象方法与方法引用的编译时类型匹配
        • 要么:
          • 引用返回void
          • 引用返回的类型可以分配给功能接口的相应类型,例如方法引用必须返回 Number 或子类型以兼容 `B foo(Function f)

        【讨论】:

        • 它不等同于匿名内部类,因为 lambdas 不会将 $this 捕获为字段
        • @the8472 啊,不知道。尝试修复它,希望它没有错。感谢您指出这一点!
        【解决方案4】:

        方法引用和 lambda 是目标类型以匹配 SAM interfaces。在您的情况下,它必须匹配 I,因为这是 foo 参数的类型。

        【讨论】:

          猜你喜欢
          • 2014-10-30
          • 2019-08-10
          • 1970-01-01
          • 2017-01-22
          • 1970-01-01
          • 2015-07-04
          • 2011-01-09
          • 1970-01-01
          相关资源
          最近更新 更多