什么是方法参考的类型?

时间:2015-09-28 21:21:38

标签: java java-8 method-reference

说我们有

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

方法参考的方法1的类型是什么?

这就是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))。

这是唯一的出路吗?

4 个答案:

答案 0 :(得分:3)

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

答案 1 :(得分:1)

非正式解释:

请记住,方法引用可以被认为是一些lambda的替代语法,而lambdas都实现了一个或多个functional interfaces

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

所以

foo (A::method1);

可以成为

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

可以缩减为匿名类:

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

这是一个匿名类,它是Function

的子类型

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

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

如果符合以下情况,方法参考可用作T类型:

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

答案 2 :(得分:1)

您可以使用现有的BiFunction

,而不是声明新界面
import com.jayway.restassured.path.json.JsonPath;

String json = "{\"fields\":{\"field1\":1,\"field2\":2,\"field3\":3,\"field4\":\"4\"}}";

// The value of the JsonPath object stays in the correct order: {"fields":{"field1":1,"field2":2,"field3":3,"field4":"4"}}
JsonPath jsonpath = new JsonPath(json);

// When using any of the JsonPath methods the order is messed up and returns: "{field4=4, field3=3, field2=2, field1=1}"
Object map = jsonpath.getMap("fields");

答案 3 :(得分:0)

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

  1. 使用简写语法设置实现功能界面的匿名类 - 这很好。
  2. 让编译器知道使用A::method1作为I.m的实现 - 这也很好。
  3. 因为A::method1已经存在,你可以使用方法引用而不是lambda表达式 - 这也很好。
  4. 传递实际参数c,该参数在行foob=i.m(a,c)方法的正文中完成。此处用于c的实际参数应传递给A::method1
  5. a中的对象a.method1仍然是任意,因为您指定Class::Method而非Instance::Method