阅读更多

2顶
5踩

编程语言

转载新闻 如何避免 Lambda 表达式毁了你的世界

2014-03-31 14:20 by 副主编 WnouM 评论(16) 有16373人浏览



代码与野兽

在Java8中,引入的Lambda表达式无疑是最受关注的。但是自这个新闻被公布的几个月以来,我还没见到过有哪些项目是Lambda起着关键作用的。

确实,众人所知的Lambda表达式一直被学术界、研讨会和社区宣扬对java是百利而无一害。但是经过时间的考验后,Lamdba是否依然像培根芝士汉堡那样美妙而又让人称赞呢?你又是否会因为日常工作需要用到它而去寻找更多关于Lamdba的资料呢?

让我们马上来看看奇妙的Lambda表达式在我们的代码中的运用:

public class RuinLambdas {
    public static void main(String[] args) {
        // Easy
        startDream(new Dream() {
            @Override public void dream() {
                // Dream boy, dream ...
            }
        });
  
        startDream(new AugmentedDream() {
            @Override public void dream(String dreamName) {
                // Dream boy, dream ...
            }
        });
  
        // Less easy
        startDream(() -> { /* Dream boy, dream ... */ });
  
        // And now kid ? ...
        startDream((dreamName) -> { /* Dream boy, dream ... */ });
  
        // Do you see which one it is directly by reading this ? ...
        startDream((dreamName, duration) -> { /* Dream boy, dream ... */ });
    }
  
    public static void startDream(Dream md) { md.dream(); }
  
    public static boolean startDream(AugmentedDream ad) {
        ad.dream("Ruin lambdas");
        return true;
    }
  
    public static boolean startDream(ThisIsNightmare hahaha) {
        hahaha.sufferMyKid("Hahaha you're going to hell", 2000);
        return false;
    }
}
  
interface Dream {
    void dream();
}
  
interface AugmentedDream {
    void dream(String dreamName);
}
  
interface ThisIsNightmare {
    void sufferMyKid(String dreamName, int duration);
}


代码内容:一个类有三个方法,开始做美梦,还有另外一个方法,是做噩梦的。

该如何看待、使用、欣赏以及理解(Lamdba)?

通过注释,我们可以很简单的明白一些事实:

  • 通过每个方法的直接调用我们知道使用哪个接口;
  • 通过每个调用我们知道哪些方法被实现了;
  • 就算没有解释,代码一样简洁易读;
  • 开发人员不需要理解代码的每一个细节;
  • 初级开发人员加入团队并没有迷失在代码荒漠中。
那接下来是否应该讲讲怎样使用Lambda了?不,如果这样的话就跟前文相抵触了。

的确,对于绝大部分不善于编程的人来说,这些代码并不那么易读了。你可能会反驳:只要你看看下面的注释就明白所有(代码)了。是不是这样呢?可能在某些情况下,的确如此,但是生活可不像你开着法拉利在空荡的高速公路上一样畅通无阻。为什么会这样?

谁最不喜欢Lambda?

成为一个Lambda十分的艰难,把难读且难用的Lambda当作一个人的话,问问他这些问题:你有没有一些简单的项目是所有的代码都写在一个类里面的?你有没有维护过几个星期以前甚至是几个月以前的代码?你没有写过代码了吗?

在现实生活中,你用Maven或者Gradle来管理依赖。你也基本上是用IDE来开发你的应用吧?通过这两件事你可能理解Lambda的难用了。

日常工作中的Lambda和依赖管理

开发中,你一般都没有(去找)你用的库的源代码。当你用了Lamdba这样简洁的语法的时候,你就必须通过浏览API文档来使用这些库了。当你不能理解你使用的库的时候,你可能需要花几个小时去理解库函数做了什么。而Lamdba简洁的语法对你理解这些代码没有任何帮助。

当Lambda没有IDE

我们都习惯使用IDE中Ctrl +点击的快捷方式帮我们找源代码的声明、实现。用的很爽是吧?别以为这是IDE必须做的,假如没有IDE,你要在你的服务器上用 vi 来写你的java代码了(vi?这是什么时代的东西了:)),到时候你会用不一样的态度来看待IDE了。

在“不懂就GOOGLE的时代”,你会说让你理解这些代码不是什么难事。以程序员的经验来说,确实如此。如果你的Java足够好的话,你甚至可以通过在虚拟机里查看、编写字节码来理解程序。但是当你正着手一个新项目,而且因为你的上司看到你找一个bug找了几个星期没找出来的时候,你就会焦虑起来,事情也会变得棘手了。

Lambda有个矛盾就是它的语法写起来简单但是却难以理解,除非你对它十分熟悉。所以,如果你要快速弄清楚代码做了什么,即使它简化了Java的语法,但是lambda让代码变得抽象,难以迅速的理解。

Lambda——我依然爱你

就算这文章有损lambda表达式在Java8变革中的声誉,我还是爱它们。事实上,如果你已经习惯了它们,它们真的很好用,主要用于快速处理列表中每个元素的值。

对于复杂的算法也许有些开发者会认为以上的观点不正确。 Java的从来就不是一个函数式语言,但现在Lambda却成为了Java的核心。个人认为事事无绝对的好坏,我们不可能只保留Lambda的好处又让它变得易读吧?上下文是很重要的,你不会开着载着水泥的卡车跑去超市就为了买瓶牛奶吧?

我不确定我是否是唯一一个对Java8引入lambda抱有一百分感兴趣的人,你可以留下您的意见,无论你是否同意我的看法。

最后,我想给你留下一个小小的Lambda表达式(作为礼物)……

readers.stream() .filter(reader -> reader.isNinja()) .forEach(reader -> reader.cheers());


原文链接: zeroturnaround 翻译: ImportNew.com - 陈秋林
译文链接: http://www.importnew.com/10480.html
  • 大小: 69.3 KB
来自: importnew
2
5
评论 共 16 条 请登录后发表评论
16 楼 非法用户 2014-04-07 19:25
请用过后再来评价,合理使用,代码简洁很多
15 楼 crazy.j 2014-04-06 01:18
接受能力问题吧,一时间你家冲进来一个外星人跟你称兄道弟住下了,有些人可能会觉得很高兴,有些人需要时间接受,有些人可能会把他撵走。
14 楼 someone 2014-04-05 15:50
真心觉得看起来很费劲
13 楼 q269223 2014-04-04 17:35
iOracleSun 写道
绝对是恶梦。

绝对是一场噩梦·
12 楼 haroldshen 2014-04-04 11:57
呵呵,我是.net 和 Java 都做,在.net 没引入 Lambda 时,我也觉得 Lambda 太 难懂了,可是当我用的多了,其实才了解 Lambda 的好处。

我了解的 Lambda 其实是更高一层的抽象,没有lambda,我们要在一个列表中查找 几个 数字大于3 的数字,那么肯定是 for 循环去做(这就是程序员思维啊)
但是 lambda 是让你从 人的思维来 考量:
首先你给它 要筛选的那些人,再给它一个标准,然后 它就会 将结果给你,这就是 人的思维,不需要知道什么 for, if 这些。
说白了,就是 一种 语义编程。

11 楼 kidneyball 2014-04-02 10:47
zoozooll 写道
yixiandave 写道
Lambda应用领域没有想象中那么广阔,因为你依然需要事先定义好一个函数式接口
也就是说我们依然没办法在不依赖接口的前提下搞定类似
(int a,int b)->a+b

这种的简单函数,更没办法像Groovy中的Clouse语法块可以被轻松存入一个属性并调用。
另外,Lambda内引用的外部变量被隐式的定义为了final也大大限制了其应用范围,而且这一点让我很费解,为了节省一个final关键字导致的代码歧义是难以想象的,要么就允许变化。

至于5楼说的我也比较认同,default方法的定义颠覆了Interface的定义,我想是开发人员尝试以这种方式实现java的多继承,但是真的没有更好的方案了吗


不说这么多的东西了,我倒觉得java8这些特征多少偏离了原本定义的东西,那么造成的变化可能会:
1. 接口加个default关键字就可以实现一个有实体的方法,那么会有很多人尝试多重继承;
2. (int a,int b)->a+b  对类型的不限制,确实很大程度上改变了java强类型原则。强类型语言的一个特点是ide debug方便
3.  Lambda内引用的外部变量被隐式的定义为了final也大大限制了其应用范围。如果IDE没有加入相应的功能,我想到时候编译error层出不穷。
不过新语言这个东西哎,要大规模应用时间还远的了。有一些人自以为他们项目是java8的,其实他们所有语法都是7以下,甚至6以下,只不过用了一个jdk8而下。这种新东西要用得心应手,甚至成为一种思想,有一段路呢。要想象《java编程思想》这本书是在java出来多久后才出版的。
不过我觉得这种java8推广开来,《java编程思想》都有点过时的味道了。


1. java8的default与多继承完全是两回事,首先你不能同时继承自两个包含了相同default方法的接口,其次default方法是不能在实现类中用super调用的。

Java8引入default的作用是:假如你公开了一个接口,而别人已经基于这个接口实现了一些东西。现在你给这个接口加入一个新方法,在java8之前所有基于这个接口的实现类都会出错,也就是别人无法直接升级到最新版了。在java8里你可以给你的新方法定义一个default的空实现,而保证别人能顺利升级。

2. Java8的Lambda是限制类型的,只不过不需要在使用Lambda的位置显式写出来而已。楼上说的“不能在不依赖接口的前提下直接这样用”

3. Lambda引入了“事实final”这个概念,至少IDEA在13.0 EAP(去年底)时就已经能正确检查出来了。
10 楼 zoozooll 2014-04-02 09:48
yixiandave 写道
Lambda应用领域没有想象中那么广阔,因为你依然需要事先定义好一个函数式接口
也就是说我们依然没办法在不依赖接口的前提下搞定类似
(int a,int b)->a+b

这种的简单函数,更没办法像Groovy中的Clouse语法块可以被轻松存入一个属性并调用。
另外,Lambda内引用的外部变量被隐式的定义为了final也大大限制了其应用范围,而且这一点让我很费解,为了节省一个final关键字导致的代码歧义是难以想象的,要么就允许变化。

至于5楼说的我也比较认同,default方法的定义颠覆了Interface的定义,我想是开发人员尝试以这种方式实现java的多继承,但是真的没有更好的方案了吗


不说这么多的东西了,我倒觉得java8这些特征多少偏离了原本定义的东西,那么造成的变化可能会:
1. 接口加个default关键字就可以实现一个有实体的方法,那么会有很多人尝试多重继承;
2. (int a,int b)->a+b  对类型的不限制,确实很大程度上改变了java强类型原则。强类型语言的一个特点是ide debug方便
3.  Lambda内引用的外部变量被隐式的定义为了final也大大限制了其应用范围。如果IDE没有加入相应的功能,我想到时候编译error层出不穷。
不过新语言这个东西哎,要大规模应用时间还远的了。有一些人自以为他们项目是java8的,其实他们所有语法都是7以下,甚至6以下,只不过用了一个jdk8而下。这种新东西要用得心应手,甚至成为一种思想,有一段路呢。要想象《java编程思想》这本书是在java出来多久后才出版的。
不过我觉得这种java8推广开来,《java编程思想》都有点过时的味道了。
9 楼 caqis 2014-04-02 09:07
java 还是应该要坚持简单路线;
8 楼 freezingsky 2014-04-02 00:25
提供了特性,用不用,看自己喜好了!
7 楼 zoozooll 2014-04-01 11:54
sayji 写道
icefishc 写道
主流语言中恐怕只有c和sql不支持这东西了。 完全不理解为啥还有这么多人视它为洪水猛兽。

因为它不是命令式语言的特点,这是从函数式语言而来的东西,有人会有洁癖。


不过我倒觉得,某些程度上C的函数指针,类似于上面的东西。这个Lambda在某些程度来说也许是补充了由于java去掉了函数指针而造成的功能缺陷。当然这个只是个人看法。
6 楼 yixiandave 2014-04-01 11:53
Lambda应用领域没有想象中那么广阔,因为你依然需要事先定义好一个函数式接口
也就是说我们依然没办法在不依赖接口的前提下搞定类似
(int a,int b)->a+b

这种的简单函数,更没办法像Groovy中的Clouse语法块可以被轻松存入一个属性并调用。
另外,Lambda内引用的外部变量被隐式的定义为了final也大大限制了其应用范围,而且这一点让我很费解,为了节省一个final关键字导致的代码歧义是难以想象的,要么就允许变化。

至于5楼说的我也比较认同,default方法的定义颠覆了Interface的定义,我想是开发人员尝试以这种方式实现java的多继承,但是真的没有更好的方案了吗
5 楼 sayji 2014-03-31 21:54
Lambda没什么。不过让人不爽的是,接口中有实现方法,defualt方法就不说了,为什么java8的接口可以有静态的已实现的方法?这不是违反了接口的抽象性,破坏了类-抽象类-接口这一整套抽象层次吗?如果说函数式接口是java8良好的扩展,那default那是剑走偏锋的小破坏,那接口中可定义已实现的静态方法,那就是将接口原有的概念一击即溃。
4 楼 sayji 2014-03-31 21:42
icefishc 写道
主流语言中恐怕只有c和sql不支持这东西了。 完全不理解为啥还有这么多人视它为洪水猛兽。

因为它不是命令式语言的特点,这是从函数式语言而来的东西,有人会有洁癖。
3 楼 nick.s.ni 2014-03-31 15:00
写起来很爽,维护起来可能没以前爽了,要看写的人的规范。
2 楼 icefishc 2014-03-31 14:32
主流语言中恐怕只有c和sql不支持这东西了。 完全不理解为啥还有这么多人视它为洪水猛兽。
1 楼 iOracleSun 2014-03-31 14:27
绝对是恶梦。

发表评论

您还没有登录,请您登录后再发表评论

相关推荐

  • JDK1.8的新特性之Lambda表达式

    (一)JDK1.8的新特性之Lambda表达式 什么是Lambda表达式? 可以将Lambda表达式理解为一个匿名函数; Lambda表达式允许将一个函数作为另外一个函数的参数; 我们可以把 Lambda 表达式理解为是一段可以传递的代码...

  • Java 8 学习--lambda表达式的月之暗面

    lambda表达式何时不受欢迎 文中还列举了一些不希望碰到lambda的场景 1. 对于没有接触过lambda表达式的团队成员,突然看到lambda表达式的写法, 极有可能不知所措

  • 学透JavaScript 你真的懂 Array 吗?

    前言 科普 JavaScript,揭开 JavaScript 神秘面纱,直击 JavaScript 灵魂。此系列文章适合任何人阅读。... 如果你想用 Array,而又不想学 API 的办法。 标准规范以外的 Array API 扩展。 V8 引擎对 Array 的处...

  • Java 设计模式最佳实践:一、从面向对象到函数式编程

    大多数函数式语言都是基于 Lambda 演算的,Lambda 演算是由数学家 Alonzo Church 在 20 世纪 30 年代创建的一种形式化的数理逻辑系统。 函数式语言在那个时代如此流行的原因之一是它们可以很容易地在并行环境中运行...

  • 细说 Java 主流日志工具库

    在 Java 世界,有很多的日志工具库来实现日志功能,避免了我们重复造轮子。 我们先来逐一了解一下主流日志工具。 日志框架 java.util.logging (JUL) JDK1.4 开始,通过 java.util.logging 提供日志功能。 它能满足...

  • Java的第20年:Java和我的故事

    盛开得再绚烂的花也免不了有凋谢的时候,日中则昃月满则亏,Java这朵程序设计语言中的奇葩也摆脱不了自然的规律,从下面的图中你可以发现,Java语言在经历了它的人生巅峰以后已经走了很长时间的下坡路,尤其是在甲骨...

  • Java核心技术卷一第六章读书笔记

    文章目录6.1 接口6.2 接口示例6.3 lambda表达式6.4 内部类 6.1 接口 接口:主要用来描述类具有什么功能,而并不需要给出每个功能的具体实现 lambda表达式:一种可以在将来某个时间点执行的代码块的简介方法 在Java...

  • 一本你必须知道的.net

    《你必须知道的.NET》 作者简介:王涛 微软C# MVP,高级软件工程师,机械工程硕士,主要研究方向为.NET底层架构和企业级系统应用。现就职于某软件公司负责架构设计、软件开发和项目管理方面的工作。作者对.NET基础...

  • 私人学习

    虽然我对你的列表一无所知,但我的列表却是一大堆关于函数式编程的文章。而这些基本上是最难阅读的了。它们用枯燥的学院派 语言写成,即使“在华尔街行业浸淫十年的专家(veterans)”也不能理解函数式编程(也写作...

  • 你真的了解字典(Dictionary)吗? C# Memory Cache 踩坑记录 .net 泛型 结构化CSS设计思维 WinForm POST上传与后台接收 高效实用的.NET开源项目...

    你真的了解字典(Dictionary)吗? 从一道亲身经历的面试题说起 半年前,我参加我现在所在公司的面试,面试官给了一道题,说有一个Y形的链表,知道起始节点,找出交叉节点.为了便于描述,我把上面的那条线路称为线路1...

  • 《第一行代码 第三版》学习笔记

    其实Java虚拟机并不会直接和你编写的Java代码打交道,而是和编译之后生成的class文件打交道。而Kotlin也有一个自己的编译器,它可以将Kotlin代码也编译成同样规格的class文件。Java虚拟机不会关心class文件是从Java...

  • Java 8学习资料汇总

    Java 8发布已经有一段时间,它被认为是Java 5发布以来...Lambda表达式、默认方法、并行API等都受到了开发者的追捧,社区上关于Java 8的学习资料如雨后春笋般涌现。下面是一些优秀的学习资料汇总: Brian Goetz在S...

  • Java 8 学习资料汇总【转载】

    如何避免 Lambda 表达式毁了你的世界 如何组织你的数据流并避免使用回调函数? Takipi 博客 与 ZeroTurnaround 一样,Takipi 也提供了 Java 8 的相关文章,篇篇精彩: Java 8:StampedLock,...

  • python花树_续延,有什么难的……

    你觉得是这些表达式包围了洞,但是没了这个洞,这些表达式是没意义的,等同于不存在。 倘若还是没开窍,那就拿一只杯子。将杯子的内部视为「外」,将杯子的外部视为「内」,那么这个杯子就包含了整个宇宙。倘若这个...

  • Python网络数据采集

    Lambda表达式  本质上就是一个函数 可以作为其他函数的 变量使用 一个函数不是定义成f(x,y) 而是定义成 f(g(x),y) 或者f(g(x),h(x))的形式 ---- BeautifulSoup允许我们把特定函数类型当作findAll函数...

  • python中factor函数_Python基础教程

    ","***"] >>> filter(func,seq) ['foo','x41'] 本例中,使用列表推导式可以不用专门定义一个函数: >>> [x for x in seq if x.isalnum()] ['foo','x41'] 事实上,还有个叫做lambda表达式的特性,可以创建短小的函数...

  • 组成原理课程实验:MIPS 流水线CPU、实现36条指令、转发、冒险检测-内含源码和说明书.zip

    组成原理课程实验:MIPS 流水线CPU、实现36条指令、转发、冒险检测-内含源码和说明书.zip

  • setuptools-50.0.2-py3-none-any.whl

    Python库是一组预先编写的代码模块,旨在帮助开发者实现特定的编程任务,无需从零开始编写代码。这些库可以包括各种功能,如数学运算、文件操作、数据分析和网络编程等。Python社区提供了大量的第三方库,如NumPy、Pandas和Requests,极大地丰富了Python的应用领域,从数据科学到Web开发。Python库的丰富性是Python成为最受欢迎的编程语言之一的关键原因之一。这些库不仅为初学者提供了快速入门的途径,而且为经验丰富的开发者提供了强大的工具,以高效率、高质量地完成复杂任务。例如,Matplotlib和Seaborn库在数据可视化领域内非常受欢迎,它们提供了广泛的工具和技术,可以创建高度定制化的图表和图形,帮助数据科学家和分析师在数据探索和结果展示中更有效地传达信息。

  • setuptools-1.1.6.tar.gz

    Python库是一组预先编写的代码模块,旨在帮助开发者实现特定的编程任务,无需从零开始编写代码。这些库可以包括各种功能,如数学运算、文件操作、数据分析和网络编程等。Python社区提供了大量的第三方库,如NumPy、Pandas和Requests,极大地丰富了Python的应用领域,从数据科学到Web开发。Python库的丰富性是Python成为最受欢迎的编程语言之一的关键原因之一。这些库不仅为初学者提供了快速入门的途径,而且为经验丰富的开发者提供了强大的工具,以高效率、高质量地完成复杂任务。例如,Matplotlib和Seaborn库在数据可视化领域内非常受欢迎,它们提供了广泛的工具和技术,可以创建高度定制化的图表和图形,帮助数据科学家和分析师在数据探索和结果展示中更有效地传达信息。

  • CEA二次开发脚本:用于ECSP配比设计

    CEA二次开发脚本:用于ECSP配比设计

Global site tag (gtag.js) - Google Analytics