lambda表达式与静态方法

时间:2017-05-29 17:11:35

标签: java lambda functional-programming java-8 static-methods

我有一个关于没有代码重复的lambda表达式的可重用性的问题。例如,如果我有一个辅助方法,我可以很容易地将它编码为静态方法,并且可以从其他类中引用它而不需要代码重复。这怎么会在lambda表达式中起作用? 示例:我编写了以下静态方法

public class MyUtil {

    public static int doubleMe(int x) {
        return x * 2;
    }
}

我可以在整个项目的多个位置重复使用相同的方法而不需要代码重复

public class A {

    public void someOtherCalculation() {
        MyUtil.doubleMe(5);
    }
}

public class B {

    public void myCalculation() {
        MyUtil.doubleMe(3);
    }
}

当涉及到lambda函数时,它如何工作,编写一次函数并在多个类中使用相同的函数。

Function<Integer, Integer> doubleFunction = x -> x * 2;

在我的例子中,我将在哪里编写上述lambda函数,以及如何在A类和B类中重用它?

5 个答案:

答案 0 :(得分:7)

  

我在哪里写上面的lambda函数

由于您的函数未引用任何字段,因此将其放在静态最终字段中是合适的:

class Utility {
    public static final Function<Integer,Integer> doubleFunction = x -> x * 2;
}
  

如何在A类和B类中重复使用它?

您可以将其称为Utility.doubleFunction,并将其传递到需要它的上下文中:

callMethodWithLambda(Utility.doubleFunction);

请注意,方法引用允许您定义一个函数,并将其用作lambda:

class Utility {
    public static Integer doubleFunction(Integer x) {
        return x*2;
    }
}
...
callMethodWithLambda(Utility::doubleFunction);

这种方法非常灵活,因为它允许您在多个上下文中重用相同的代码。

答案 1 :(得分:3)

实际上,匿名函数适用于代码重用不是的情况。

愚蠢的例子,但是说你正在使用map为列表中的每个数字添加两个。如果这是您可能需要的常见操作,那么将数字加2的静态函数比在任何地方编写相同的lambda更有意义。

但是,如果你有一个功能可以在列表中添加两个,那么定义&#34;添加两个&#34;更有意义。本地作为lambda运行,因此您不会使用其他任何地方都不需要的代码来插入您的类。

在编写广泛使用高阶函数的Clojure时,我常常创建本地匿名函数来整理&#34; full&#34;中的代码。我写的功能。绝大多数这些匿名函数在&#34;全球&#34;中是非感性的。范围(或类范围);特别是因为他们通常关闭局部变量,因此无论如何它们都不是全局的。

答案 2 :(得分:2)

使用lambda表达式,您不必担心可重用性(事实上,大多数lambda都没有被重用)。如果您希望Function指针指向此方法,您可以声明如下所示:

Function<Integer, Integer> doubleFunction = MyUtil::doubleMe;

并将其传递给任何方法或流以应用/映射,例如:

public static void consume(Function<Integer, Integer> consumer, int value){
    System.out.println(consumer.apply(value));
}

public static void main(String[] args) throws Exception{
    Function<Integer, Integer> doubleFunction = MyUtil::doubleMe;
    consume(doubleFunction, 5);
}

答案 3 :(得分:2)

与其他答案不同。我想用TDD方式回答你的问题。

如果你的doubleMe就像你写的那么简单,那就是你应该停止滥用方法表达式引用并直接将其作为常用的方法调用来调用。

IF 您的doubleMe非常复杂,以至于您想要独立测试doubleMe,您需要通过依赖注入来明确隐含依赖关系,以测试它们是否可以通过他们的通信协议。但java不能直接引用方法,除非你使用反射api Method /使用实现 SAM 接口的匿名类,该接口在jdk-8之前将请求委托给方法。您可以将一个方法表达式引用引用到jdk-8中的功能接口,这很开心。所以你可以通过使用功能接口使隐式依赖显式,然后我想编写一些通信协议测试如下:

@Test
void applyingMultiplicationWhenCalculating???(){
    IntUnaryOperator multiplication = mock(IntUnaryOperator.class);
    B it = new B(multiplication);

    it.myCalculation();

    verify(multiplication).applyAsInt(3);
}

AND 然后你的类如B应用依赖注入更像是如下:

public class B {
    IntUnaryOperator multiplication;

    public B(IntUnaryOperator multiplication){
          this.multiplication = multiplication;
    }

    public void myCalculation() {
          multiplication.applyAsInt(3);
    }
}

THEN 您可以通过将方法表达式引用引用到功能接口来重用方法,如下所示:

A a = new A(MyUtil::doubleMe);
B b = new B(MyUtil::doubleMe);

答案 4 :(得分:0)

您可以执行以下操作。

class Fn {
  public static final Function<Integer, Integer> X2TIMES = x -> x *2;
}

class Test {
  public static void main (String[] args) {
    System.out.println(Fn.X2TIMES.apply(5));
  }
}