Java 8围绕着作为一等公民的功能跳舞?

时间:2014-03-26 15:08:22

标签: java java-8 first-class-functions

因此,我的函数式程序员喜欢像python这样的语言,将函数视为一等公民。看起来Java 8已经屈服于压力和#34;"实现了lambda表达式和方法引用之类的东西。

我的问题是,Java是否正在使用第一类函数,或者这实际上只是语法糖来减少实现匿名类/接口(如runnable)所需的代码量? (我的直觉说后者)。

我的理想情景

Map<String,DoubleToDoubleFunc> mymap = new HashMap<String,DoubleToDoubleFunc>();
...
mymap.put("Func 1", (double a, double b) -> a + b);
mymap.put("Func 2", Math::pow);
...
w = mymap.get("Func 1")(y,z);
x = mymap.get("Func 2")(y,z);

4 个答案:

答案 0 :(得分:4)

没有function structural type in Java 8。但Java始终拥有一流的对象。事实上,它们已被用作替代品。从历史上看,由于缺少一流函数,我们到目前为止所做的是将函数包装在一个对象中。这些是着名的SAM类型(单一抽象方法类型)。

所以,而不是

function run() {}
Thread t = new Thread(run);

我们

Runnable run = new Runnable(){ public void run(){} };
Thread t = new Thread(run);

也就是说,我们将函数放在一个对象中,以便能够将它作为值传递。因此,一流的对象长期以来一直是替代解决方案。

JDK 8简化了这个概念的实现,他们称之为这种类型的包装器接口和功能接口&#34;并提供一些语法糖来实现包装器对象。

Runnable run = () -> {};
Thread t = new Thread(run);

但最终,我们仍在使用一流的对象。它们具有与一流功能类似的特性。它们封装了行为,它们可以作为参数传递并作为值返回。

lambda mailing list Brian Goetz对推动这种设计的一些原因作了很好的解释。

  

按照我们今天讨论的方式,这里有一个方面   我们在哪里前进。我们探索了&#34;也许是lambdas的道路   只是内部类实例,这将非常简单&#34;,但是   最终来到了&#34;职能是一个更好的方向   为了语言的未来&#34;。

     

这种探索分阶段进行:首先在EG之前进行   成立,然后当EG讨论问题时再次成立。该   以下是我对这个问题的立场。希望,这填补了一些   目前的规范和我们所说的内容之间的差距   关于它。

     

关于lambdas是对象还是对象的问题   并不是很大程度上归结为哲学问题,例如&#34;什么是   lambdas真的&#34;,&#34;为什么Java会受益于lambdas&#34;,最终   &#34;如何最好地发展Java语言和平台。&#34;

     甲骨文的立场是Java必须发展 - 当然要小心 -   为了保持竞争力。当然,这很困难   平衡行为。

     

我相信,发展Java的最佳方向是   鼓励更具功能性的编程风格。 Lambda的作用   主要是为了支持更多的发展和消费   功能类库;我提供了诸如此类的例子   filter-map-reduce来说明这个方向。

     

生态系统中有大量证据支持这一假设   如果给予工具这么容易,面向对象的程序员   准备接受功能性技术(如不变性)和   将它们用于面向对象的世界观,并将写作   因此,更好,更不容易出错的代码。简单地说,我们相信   我们可以为Java开发人员做的最好的事情是给他们一个温和的推动   更具功能性的编程风格。我们不会去   把Java变成Haskell,甚至变成Scala。但方向是   清楚。

     

Lambda是这次演变的首期付款,但它远非如此   故事的结局。故事的其余部分尚未撰写,但是   保留我们的选择是我们评估方法的一个关键方面   我们在这里做出的决定。

     

这就是为什么我一直坚持认为lambda不是   对象。我相信&#34; lambdas只是对象&#34;位置,而   非常舒适和诱人,猛烈砸门   语言演变的潜在有用方向。

     

作为一个例子,让我们看一下函数类型。 lambda strawman   devoxx提供了函数类型。我坚持要把它们删掉,然后   这让我不受欢迎。但我对函数类型的反对并非如此   我不喜欢功能类型 - 我喜欢功能类型 - 但是那样   函数类型与Java类型的现有方面严重冲突   系统,擦除。删除的功能类型是两个世界中最糟糕的。   所以我们从设计中删除了它。

     

但我不愿意说#34; Java永远不会有功能类型&#34;   (虽然我认识到Java可能永远不会有函数类型。)I   相信为了获得功能类型,我们必须先处理   擦除。这可能是,也可能是不可能的。但在一个世界   具体的结构类型,功能类型开始做更多   感。

     

世界的lambdas-are-objects视图与此可能发生冲突   未来。 lambdas-are-functions对世界的看法并没有   保持这种灵活性是支持不这样做的一个要点   即使是对象的外观,也会给lambda带来负担。

     

您可能认为当前的设计与对象紧密相关   lambdas的框 - SAM类型 - 使它们成为有效的对象   无论如何。但是这已经被小心地从表面区域隐藏起来了   为了让我们能够考虑“赤身裸体”。 lambda在将来,或考虑   lambdas的其他转换上下文,或者更多地集成lambdas   紧紧地控制构造。我们现在不这样做,而且我们   甚至没有这样做的具体计划,但能够做到   未来可能会这样做是设计的关键部分。

     

我对Java的未来感到乐观,但我们有时会继续前进   不得不放弃一些舒适的想法。 Lambdas-are-functions打开   门。 Lambdas-are-objects关闭它们。我们更愿意看到那些门   离开了。

答案 1 :(得分:2)

他们并非真正的IMO一流功能。 Lambda最终是功能接口的一个实例。但它确实为您提供了一流功能的优势。您可以将它作为参数传递给需要功能接口实例的方法。您可以将其分配给变量,在这种情况下,将使用目标类型推断其类型。您可以从方法中返回它,等等。

此外,lambdas并不能完全取代匿名类。并非所有匿名类都可以转换为lambda。你可以通过this answer获得关于两者之间差异的一个很好的解释。所以,没有lambdas不是匿名类的语法糖。

答案 2 :(得分:1)

匿名课程不是语法糖;它编写的内容有点涉及。 (并不是说这样做是错误的; 任何语言都有自己的实现细节,如何编译lambdas,而Java并不比其他许多语言差。)

请参阅http://cr.openjdk.java.net/~briangoetz/lambda/lambda-translation.html了解完整的细节。

答案 3 :(得分:1)

interface DoubleDoubleToDoubleFunc {
    double f(double x, double y);
}

public static void main(String[] args) {
    Map<String, DoubleDoubleToDoubleFunc> mymap = new HashMap<>();
    mymap.put("Func 1", (double a, double b) -> a + b);
    mymap.put("Func 2", Math::pow);
    double y = 2.0;
    double z = 3.0;
    double w = mymap.get("Func 1").f(y,z);
    double v = mymap.get("Func 2").f(y,z);
}

所以它仍然是语法糖,只是在某种程度上。