本篇文章不介绍Lambda的前世今生,这里只对Lambda表达的应用做详细了解。以及与内部类的差异点。

Lambda表达式

Lambda表达式是Java SE 8版本中引入的新的语法糖。将功能看做方法参数,将代码看做数据。

Lambda表达式语法:

LambdaParameters -> LambdaBody

Lambda表达式分为三部分:

  • 参数列表
  • ->符号
  • 函数体

如:

() -> {} // 无参,返回结果为空
(x) -> System.out.println(x); // 带有一个参数
(Thread t) -> { t.start(); } // 带有一个申明参数
(int x, int y) -> x + y; // 带有两个申明参数,一个方法参数;
(int x, int y) -> return x +y; // 带有两个申明参数,一个方法参数;
(x, y) -> return x +y; // 带有两个申明参数,一个方法参数;

总体上表现如上形式,是Java中一种新的风格的表达式,和普通的表达的确有很大风格上的差异性。

这种风格的语法优势:

  • 语法特点决定了语句的简洁紧凑,通过减少申明类型、return、单行语句去括号等等从而变得更精简;

  • 具有更强的表达能力,减少冗余的代码,从而更关注真正的功能语句,语义更精确清晰;

函数式接口

已经对lambda表达式定义好了,但是如何在兼容面向对象的Java体系中使用。在面向对象体系中,一切皆是对象,怎样将这种表达式作为对象去使用,从而引入函数使接口:只有一个抽象方法的接口,代表着单功能的契约

为了区分函数式接口和只包含一个抽象方法的普通接口,需要使用@FunctionalInterface注解标注接口,这样编译器就能将其作为函数式接口处理。

注:无论是本身具有还是继承都可以。如果继承父接口的抽象方法,也算入函数式接口一个抽象方法的统计中;如果覆盖Object类的方法,不会算入统计中,因为任何对象都继承自Object

有了函数式接口就可以很方便的使用lambda表达式,使用Java来进行函数式编程。

Function<String, String> f = (String x) -> x.toUpperCase();
f.apply("msg");

lambda表达式可以赋值给函数式接口,这里涉及到目标类型上下文,编译器根据lambda表达式所在的上下文推导其目标类型为Function。

List<String> list = new ArrayList<>();
list.forEach((x) -> System.out.println(x));

lambda表达式作为方法参数,其实是list.forEach方法中的方法参数是函数式接口,编译器推导lambda表达式类型为forEach中的函数式接口类型作为lambda表达式的目标类型。

从以上可以看出:

  • lambda表达式的目标类型必须是函数式接口,但是函数式接口和lambda表达式是两部分,函数式接口并不属于lambda表达式一部分,只是作为其目标类型;

  • 函数式接口的抽象方法参数必须与lambda表达式的相一致:数量和个数;

  • 函数式接口抽象方法返回参数与lambda表达式返回值一致:类型;

  • lambda表达式中抛出的受检异常与函数式接口抽象方法上的throws保持一致;

函数式接口使得lambda表达式能够更好的使用。Java是面向对象,如果在此基础上引入lambda,势必需要向前兼容:

  • 如果引入新的类型,势必要与旧的api形成两套体系,这样就无法在历史版本中使用lambda表达式;

  • 如果引入新的类型,Java类库需要对于同一功能就需要维护两份:过去历史版本/lambda版本;

如果使用已有的接口表示:

  • 接口是 Java 类型系统的一部分

  • 接口天然就拥有其运行时表示(Runtime representation);

基于这些原因,选择已有的接口类型作为函数式接口,然后引入lambda表达式是最折中平衡的方式。

Lambda表达式与匿名内部类

  1. lambda表达式的简洁、紧凑的语法结构是匿名内部类所不能比拟的;

  2. lambda表达式具有更明确的语义——因为只关注有效的代码;

  3. lambda表达式的作用域比匿名内部类更加有友好(词法作用域/新的内部作用域):this在lambda表达式中表示外部内,而在内部类中表示当前内部类实例;变量名在lambda表达式中就是表示外部的,而在内部类中要防止继承自超类———lambda的词法作用域;(Shadowing问题,如果对Shadowing不熟悉,赶紧戮Shadowing)

  4. lambda是函数式编程的体现,内部类任然是在面向对象层面;

参考

深入理解Java 8 Lambda(语言篇——lambda,方法引用,目标类型和默认方法)

The Java® Language Specification

Lambda Expressions

Java 8——Lambda表达式的更多相关文章

  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表达式10个示例【存】

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

  4. Java 8 Lambda 表达式

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

  5. Java 8 lambda表达式示例

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

  6. Java 8 Lambda 表达式详解

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

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

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

  8. Java基础学习总结(44)——10个Java 8 Lambda表达式经典示例

    Java 8 刚于几周前发布,日期是2014年3月18日,这次开创性的发布在Java社区引发了不少讨论,并让大家感到激动.特性之一便是随同发布的lambda表达式,它将允许我们将行为传到函数里.在Ja ...

  9. 02、Java的lambda表达式和JavaScript的箭头函数

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

  10. Java 8 Lambda表达式学习和理解

    Java 8 Lambda表达式和理解 说明:部分资料来源于网络 时间:20190704 Lambda 表达式,也可称为闭包,它是推动 Java 8 发布的最重要新特性.Lambda 允许把函数作为一 ...

随机推荐

  1. Spark GraphX图算法应用【分区策略、PageRank、ConnectedComponents,TriangleCount】

    一.分区策略 GraphX采用顶点分割的方式进行分布式图分区.GraphX不会沿着边划分图形,而是沿着顶点划分图形,这可以减少通信和存储的开销.从逻辑上讲,这对应于为机器分配边并允许顶点跨越多台机器. ...

  2. ETL中获取公共时间参数变量释义

  3. 一个标准sql语句模板

    select distinct top n * from t1 inner join t2 on ... join t3 on ... where ... group by ... having .. ...

  4. Semaphore的简介及应用场景

    Semaphore是一个计数信号量,常用于限制可以访问某些资源(物理或逻辑的)线程数目. 常用函数: 信号量的构造函数 非公平: public Semaphore(int permits);//per ...

  5. cookie跨域解决方案

    cookie的名/值对中的值不允许出现分号.逗号和空白符,因此在设置cookie前要用encodeURIComponent()编码,读取时再用decodeURIComponent()解码. cooki ...

  6. 部署LNMP应用平台

    一.LNMP应用平台概述 1.概述:LNMP代表的就是:Linux系统下Nginx+MySQL+PHP这种网站服务器架构.Nginx是一个高性能的HTTP和反向代理服务器,也是一个IMAP/POP3/ ...

  7. np.append()

    1.numpy.append() np.append(arr,values,axis=None) 功能:在array后面追加values 参数: arr:array_like 值将附加到此数组的副本. ...

  8. 通过async实现协程的延迟执行及结果获取

    在上一次https://www.cnblogs.com/webor2006/p/12022065.html对于协程的async和wait进行了初步的学习,其可以加速执行的性能,其实对于async它是提 ...

  9. LCD驱动程序之层次分析

    1.回顾字符设备驱动程序: 字符设备驱动编写的一般步骤: 1)主设备号 2)构造file_operations结构体体 .open = xxxx .read = xxxxx 3)register_ch ...

  10. 百度快排发包python核心源码

    本源码仅供测试,发包有风险,优化还是踏实的好!本代码是本人自己学习python练手作品!  附上代码: # -*- coding: utf-8 -*-from selenium import webd ...