使用实例类型对实例方法的方法引用

时间:2018-10-30 09:13:34

标签: java lambda functional-programming method-reference

我指的是this文章,该文章指出我们可以使用两种方法来引用实例方法:

  1. 使用实例

    obj::instanceMethod
    
  2. 使用实例类型

    ObjectType::instanceMethod
    

首先,我很容易通过简单的示例进行验证:

class DummyConsumer
{
    public void consume(String a)
    {
        System.out.println("Counsumed " + a);
    }
}

DummyConsumer d = new DummyConsumer();
Consumer<String> c1 = d::consume;     //method reference
Consumer<String> c2 = (s) -> d.consume(s);  //lambda expression
c1.accept("s");
c2.accept("d");

但是我无法使用ObjectType::instanceMethod做同样的事情。该页面上给出的示例使我很困惑,如下所示:

class Shipment {
  public double calculateWeight() { return 0d; }
}

public List<Double> calculateOnShipments(List<Shipment> l, Function<Shipment, Double> f) {
    List<Double> results = new ArrayList<>();
    for(Shipment s : l) {
      results.add(f.apply(s));
    }
    return results;
}
calculateOnShipments(l, s -> s.calculateWeight()); //lambda expression
calculateOnShipments(l, Shipment::calculateWeight); //method reference

上面最后一行的通知Shipment::calculateWeight。有人可以通过我的Consumer示例帮助我模仿吗?

1 个答案:

答案 0 :(得分:0)

您似乎可以在没有实例的情况下使用ObjectType::instanceMethod的原因是因为该方法引用表示接受ObjectType作为参数,然后是instanceMethod的参数的方法。

class A {
    public void f(String s) {}
}

在这里,您可以想到A::f代表着这样的“静态”方法:

public static void f(A a, String s) {}

因此在您的示例中,您需要一个BiConsumer来表示一个接受两个参数并且不返回任何内容的方法:

BiConsumer<DummyConsumer, String> c = DummyConsumer::consume;

Shipment情况下,Shipment::calculateWeight表示这样的“静态”方法:

public static double calculateWeight(Shipment s) { ... }

这就是Shipment::calculateWeight可以用Function<Shipment, Double>表示的原因。

因此,通常,您只需要首先弄清楚方法引用代表哪种方法,然后找到一个代表该方法的功能接口。有时,您需要自己创建一个功能接口!