Java 程序员在 Java 8 之前做了什么,如果他们想传递一个函数?

What did Java programmers do before Java 8 if they wanted to pass a function around?

请对我温柔点

我听说 Java 8 引入了 lambda。但在那之前,如果你想传递一个函数,比如说,作为参数,你做了什么?

我能想到的一种方法是像这样创建一个单一的方法接口:

public interface ISingleMethodInterface
{
  bool Really(int n);
}

public bool GimmeFunction(ISingleMethodInterface interface, int n)
{
  return interface.Really(n);
}

但作为第一个 class 公民,这是非常有限的功能应用,因为:

  1. 除了执行该函数或将该对象传递给另一个方法之外,您无能为力。使用 lambda,您可以进行组合。例如你可以像这样否定 lambda:

    public bool GimmeLambdaAndIWillComputeItsInverse(Func<int, bool> predicate, int n)
    {
      return !predicate(n);
    }
    
  2. 你不能 return lambdas 或它们的衍生物。我的意思是,您只能 return 同一个对象,如下所示:

    // I know Java doesn't have Tuples but let's forget that for now
    public Tuple GimmeFunction(ISingleMethodInterface interface, int n)
    {
      return new Tuple { Item1 = interface, Item2 = n };
    }
    

    使用 lambda 表达式,您可以 return 像这样的导数:

    public Func<int, bool> GetInverseFunction(Func<int, bool> predicate, int n)
    {
      return n => !predicate(n);
    }
    

那么,如果你需要做这样的事情,你做了什么?

一个简单地传递函数接口的实例。你对这个相对于 lambda 的诋毁有点不对劲,因为在 Java 中,lambda 实际上是函数式接口。因此,由于一个是根据另一个实施的,因此它们并不比另一个强。不同之处在于源代码的可读性如何打动您。

回到 Java 8 之前的古代,我们不得不使用笨重的旧 anonymous class syntax 来处理这种事情,导致代码看起来像这样:

object.gimmeFunction(new SingleMethodInterface(){
    @Override public bool really(int n){
        return n=="really".hashCode();
    }
});

因为这种模式很常见(请参阅 Comparator, Runnable, ActionListener), it was decided that the language could use a much cleaner syntax for it, and so in Java 8 we were given lambdas 将上面的讨厌的块变成:

object.gimmeFunction(n->n=="really".hashCode());

因此有助于保持各地 Java 程序员的理智。两者在功能上是等价的,但第一个更灵活,而第二个则更多,much更好看。