前言

在JDK8和ES6的语言发展中,在Java的lambda表达式和JavaScript的箭头函数这两者有着千丝万缕的联系;本次试图通过这篇文章弄懂上面的两个“语法糖”。

简介

Lambda 表达式来源于 C# 5.0,但又不太确定,于是查了下 百度百科:Lambda表达式,仍然没有得到明确的答案,所以懒得去纠结这个问题了。

箭头函数(arrow function),就是C#中的lambda表达式,据说Java8也把它加入了。但不管怎样,JS正在从其它语言吸纳优秀的特性(比如yield, class, 默认参数等等),且不论这些特性好坏,这件事本身就是极好的(至少我们正在使用的是一个充满活力的工具)

只是Java用->箭头,C#用的箭头与JS一样:=>,这个箭头叫“lambda运算符”,行话读作”goes to”

lambda表达式(箭头函数)据说是定义函数最简洁的方法,语法上几乎没有冗余成分了。因为JS弱类型的特点,JS中的lambda表达式要比C#和Java中的更简洁(少了参数类型声明)

一句话,箭头函数就是lambda表达式,提供了更简洁的function定义方式

lambda语法

什么是lambda?

这里先给简要的定义:将匿名函数复制给变量的简写方式的函数称为 lambda 表达式

1、java的场景中:把“一块代码”赋给一个Java变量

这个是简化过程:

2、JS中同理也是比较简单的

var fun1 = funcation(int x,int y){
return (x+y);
}

简写如下:

var fun1 = (x,y)=>x+y;

lambda的语法定义

这里由于Java一切皆对象的原因,暂时先介绍JavaScript的定义,但Java基本雷同

JavaScript的箭头函数

Lambda 表达式的主要形式是如下定义,符号的左侧是参数,右侧是表达式或语句块。

(参数列表) => { 语句块 }

当“语句块”只有一条语句的时候,可以省略大括号,就成了

(参数列表) => 语句

注意: Lambda 表达式一般是作为参数或者值使用,所以根据使用的上下文,大部分情况下编译器可以推断出 Lambda 表达式的参数类型;Lambda 表达式的参数通常是省略类型的

Java的lambda表达式

Lambda 表达式的作用其实就是匿名方法,而 Java 中并没有匿名方法这一语法。不过 Java 中有匿名对象,当你直接 new 一个接口并实现接口方法的时候,Java 编译器实际是产生了一个类(匿名类)来实现这个接口,然后再返回这个类的一个实例,也就是匿名对象;Lambda表达式本身就是一个接口的实现

这种只有一个接口函数需要被实现的接口类型,我们叫它”函数式接口“。为了避免后来的人在这个接口中增加接口函数导致其有多个接口函数需要被实现,变成"非函数接口”,我们可以在这个上面加上一个声明@FunctionalInterface, 这样别人就无法在里面添加新的接口函数了:

下面是一个完整的案例:

@FunctionalInterface
public interface WorkerInterface {
public void doSomeWork();
} public class WorkerInterfaceTest { public static void execute(WorkerInterface worker) {
worker.doSomeWork();
} public static void main(String [] args) { //invoke doSomeWork using Annonymous class
execute(new WorkerInterface() {
@Override
public void doSomeWork() {
System.out.println("Worker invoked using Anonymous class");
}
}); //invoke doSomeWork using Lambda expression
execute( () -> System.out.println("Worker invoked using Lambda expression") );
} }

lambda的常见使用场景

上面通过两个简单的案例演示了lambda,现在总结一下在Java和JavaScript常见的用法和使用常见。

java中常见的使用场景

1. 何时用?

JAVA8中就提供了这种“函数式编程”的方法 —— lambda表达式,供我们来更加简明扼要的实现内部匿名类的功能。

函数式接口:Functional Interface.

定义的一个接口,接口里面必须 有且只有一个抽象方法 ,这样的接口就成为函数式接口。

在可以使用lambda表达式的地方,方法声明时必须包含一个函数式的接口。

简单的说,凡是(java8以上)函数式接口都可以尽量使用lambda表达式,注意:如果我们提供的这个接口包含一个以上的Abstract Method,那么使用lambda表达式则会报错。建议定义的接口加上@FunctionalInterface注解。

2. 怎么用?

根据之前的思路;只要找到Java中函数式接口的皆可以放出lambda表达式的大招。

  1. JDK 8之前已有的函数式接口

    java.lang.Runnable

    java.util.concurrent.Callable

    java.security.PrivilegedAction

    java.util.Comparator

    java.io.FileFilter

    java.nio.file.PathMatcher

    java.lang.reflect.InvocationHandler

    java.beans.PropertyChangeListener

    java.awt.event.ActionListener

    javax.swing.event.ChangeListener

  2. Java SE 8中增加了一个新的包:java.util.function,它里面包含了常用的函数式接口:

补充: 关于函数式接口的详细总结

1)Java8中Iterable的foreach(Comsumer action)的函数式接口

2)Java8中Iteror的forEachRemaining(Comsumer action)的函数式接口

3)Java8中函数式接口Predicate;Collections的removeIf(Predicate filter)

...其实还有很多,就不一一列举了,其实根据规则就很容易了加上编译器优化,其实写出lambda其实也是很容易。

JavaScript的箭头函数常用场景:

由于JavaScript基于函数编程,lambda表达式非常灵活常用,基本上对于参数的简单操作都可以使用箭头函数完成,这里可以告诉你不要试图滥用。

  • 箭头函数适合于无复杂逻辑或者无副作用的纯函数场景下,例如用在map、reduce、filter的回调函数定义中;
  • 不要在最外层定义箭头函数,因为在函数内部操作this会很容易污染全局作用域。最起码在箭头函数外部包一层普通函数,将this控制在可见的范围内;
  • 如开头所述,箭头函数最吸引人的地方是简洁。在有多层函数嵌套的情况下,箭头函数的简洁性并没有很大的提升,反而影响了函数的作用范围的识别度,这种情况不建议使用箭头函数。

参考资料

02、Java的lambda表达式和JavaScript的箭头函数的更多相关文章

  1. Java 8 Lambda表达式

    Java 8 Lambda表达式探险 http://www.cnblogs.com/feichexia/archive/2012/11/15/Java8_LambdaExpression.html 为 ...

  2. 深入浅出 Java 8 Lambda 表达式

    摘要:此篇文章主要介绍 Java8 Lambda 表达式产生的背景和用法,以及 Lambda 表达式与匿名类的不同等.本文系 OneAPM 工程师编译整理. Java 是一流的面向对象语言,除了部分简 ...

  3. Java 8 lambda表达式示例

    例1.用lambda表达式实现Runnable 我开始使用Java 8时,首先做的就是使用lambda表达式替换匿名类,而实现Runnable接口是匿名类的最好示例.看一下Java 8之前的runna ...

  4. 转载:深入浅出 Java 8 Lambda 表达式

    原文地址:http://viralpatel.net/blogs/Lambda-expressions-java-tutorial/ OneAPM for Java 能够深入到所有 Java 应用内部 ...

  5. Java 8 Lambda表达式10个示例【存】

    PS:不能完全参考文章的代码,请参考这个文件http://files.cnblogs.com/files/AIThink/Test01.zip 在Java 8之前,如果想将行为传入函数,仅有的选择就是 ...

  6. 掌握 Java 8 Lambda 表达式

    Lambda 表达式 是 Java8 中最重要的功能之一.使用 Lambda 表达式 可以替代只有一个函数的接口实现,告别匿名内部类,代码看起来更简洁易懂.Lambda 表达式 同时还提升了对 集合 ...

  7. Java 8 Lambda 表达式

    Lambda 是啥玩意 简单来说,Lambda 就是一个匿名的方法,就这样,没啥特别的.它采用一种非常简洁的方式来定义方法.当你想传递可复用的方法片段时,匿名方法非常有用.例如,将一个方法传递给另外一 ...

  8. Java 8 Lambda 表达式详解

    一.Java 8 Lambda 表达式了解 参考:Java 8 Lambda 表达式 | 菜鸟教程 1.1 介绍: Lambda 表达式,也可称为闭包,是推动 Java 8 发布的最重要新特性. La ...

  9. 用Java 8 Lambda表达式实现设计模式:命令模式

    在这篇博客里,我将说明如何在使用 Java 8 Lambda表达式 的函数式编程方式 时实现 命令 设计模式 .命令模式的目标是将请求封装成一个对象,从对客户端的不同类型请求,例如队列或日志请求参数化 ...

随机推荐

  1. SQL Server温故系列(2):SQL 数据操作 CRUD 之简单查询

    1.查询语句 SELECT 1.1.查询语句的 SELECT 子句 1.2.查询语句的 FROM 子句 1.2.1.内连接查询 INNER JOIN 1.2.2.外连接查询 OUTER JOIN 1. ...

  2. Git使用小技巧之挑拣合并

    先想想一个情况,现在我们有一个功能急需要发布到线上,但是这个功能相关的代码所在的测试分(test)支有很多不应该发布的代码,那么这个时候我们就需要将与这个代码相关的提交选择性的合并到master上并发 ...

  3. SQL Server 2016 + AlwaysOn 无域集群

    目录 AlwaysOn 搭建 WSFC 配置计算机的 DNS 后缀 安装故障转移集群 验证集群 创建集群 创建文件共享见证 配置 AlwaysOn 新建可用性组 创建侦听器 可读副本的负载均衡 主角色 ...

  4. C++中 / 和 % 在分离各位时的妙用

    在学习c++的过程中,我们一般用 / 和 % 来分解数字的各个位 取整 (/) 比如1234 / 10 等于 123.4,这相当于把前三位分解出来了 取余(%) 比如 12345 的分解方法 个位:1 ...

  5. Effective Java第三版(一) ——用静态工厂代替构造器

    此文做为<Effective Java>系列的第一篇,所以有必要大概说下此书的特点,当然很多人可能都看过,毕竟是有着Java四大名著之一的大名在外,不过总会有萌新不了解,例如我!<E ...

  6. kuangbin专题 专题一 简单搜索 迷宫问题 POJ - 3984

    题目链接:https://vjudge.net/problem/POJ-3984 这个题目,emm,上代码,看的估计应该是刚开始接触搜索的,我带点注释,你能慢慢理解. #include <ios ...

  7. C++学习书籍推荐《C++ Primer 第四版》下载

    百度云及其他网盘下载地址:点我 编辑推荐 <C++ Primer中文版(第4版)>对C++基本概念和技术全面而且权威的阐述,对现代C++编程风格的强调,使<C++ Primer中文版 ...

  8. 【HDU - 1560】DNA sequence (dfs+回溯)

    DNA sequence 直接中文了 题目描述 21世纪是生物科技飞速发展的时代.我们都知道基因是由DNA组成的,而DNA的基本组成单位是A,C,G,T.在现代生物分子计算中,如何找到DNA之间的最长 ...

  9. xx.exe 中的 0x014180bd 处有未经处理的异常: 0xC0000005: 读取位置 0xfeeefeee 时发生访问冲突(当指针访问异常时,应考虑是不是对象未创建)。

    xx.exe 中的 0x014180bd 处有未经处理的异常: 0xC0000005: 读取位置 0xfeeefeee 时发生访问冲突

  10. 异步编程之Async,Await和ConfigureAwait的关系

    在.NET Framework 4.5中,async / await关键字已添加到该版本中,简化多线程操作,以使异步编程更易于使用.为了最大化利用资源而不挂起UI,你应该尽可能地尝试使用异步编程.虽然 ...